OSU eCampus CS162 Intro to Computer Science II review & recap

This post is part of an ongoing series recapping my experience in Oregon State University’s eCampus (online) post-baccalaureate Computer Science degree program. You can learn more about the program here.

Six-word summary: Brutally paced pointers pointers pointers pointers

The beatings are over I survived CS162! If you were wondering where OSU’s eCampus computer science weeder course is, this is it.

The material is challenging and the workload is punishing. The video lectures are crap, but the book is good. The class isn’t well organized (expect poorly written assignments with unclear requirements). 10 weeks is nowhere near enough.

However: I learned a lot. I got faster than I ever thought possible and worked with topics I thought would have had their own standalone courses.

In this article: topics covered in CS162, survival guide, what I thought of the class.

Note: While I normally love to post code here, I can’t share any of my project code (against student code of conduct) or specific assignment requirements, test questions, etc.

Topics covered in CS162

The class is taught in C++ and teaches (or at least requires you to know):

  • pointers to arrays
  • pointers in arrays
  • pointers to pointers
  • pointers to instances of classes
  • passing pointers to functions
  • linked lists made of pointers
  • abstract class and subclasses
  • virtual functions
  • overloading operators (give == an exciting new meaning!)
  • polymorphism
  • writing functions that do something recursively, like reverse a string, sum numbers in an array, solve a math problem
  • data structures: queue, dequeue, stack, linked lists, circularly linked lists
  • sorting algorithms


CS162 is a programming class. Like CS161, I found my Macbook to be sufficient for this class.

I don’t know why they tell people to get a Windows PC and use Visual Studio. I didn’t need it and you won’t need it – there is no assignment based on Visual Studio knowledge.

In fact, judging just by Piazza posts, a number of students seemed confused by the extra files and the “another thing to learn” factor introduced by Visual Studio.

In case you are curious: I did every assignment in Sublime Text and a Terminal window.


At any given time expect to be working on a 1-week lab assignment and a 2-week project, and mid-course, a group project on top of the first two. You will also write a multi-page document (PDF) for each project with a test plan (input, expected outcome chart), your designs, ideas you changed along the way, reflections on the assignment. This document always took me at least 3-5 hours to complete to my standards. There’s a quiz every couple weeks (15 minutes, not proctored).

I’m a proactive student who started each week’s material the moment it was released, worked on it daily, and generally finished just moments before a new load of work was dumped onto me.

The first two weeks hit like a ton of bricks: a simple Langton’s Ant simulation by itself would have been a large assignment, but CS162 adds a user-navigable menu, input validation, user-adjustable parameters (dynamically sized board, variable turns to run, etc.), and other features that have to be designed, coded, tested, debugged.

Oh, yeah – it has a visual component, too.

There are also two lab assignments to complete while you work on the Langton’s Ant project.

This pattern continues until the end of the course. The toughest week was the one where I was working on a project, a lab, and a group assignment all at the same time.

CS162 Survival Tactics

It’s easy to find people complaining online about how disorganized and intense this class is but what I really wanted when I was in the thick of it was some help. (The OSU eCampus CS subreddit is a good place to look for advice on CS162, too.)

Here’s what I did (or wish I’d done sooner) that made CS162 more bearable.

Take it by itself (if you can)

I know there are financial aid reasons not to but if you’re normally taking 2 classes a quarter, consider taking CS162 alone (or at least with fewer classes than you normally would). It’s a ton of complex material – assuming you haven’t worked a lot with C++ pointers, memory, arrays, etc. yet – and the assignments are black holes for time.

Diagram things out on paper

I found many of CS162’s assignments too complex to hold entirely in my brain.

For example, here’s a crazy thing we did: create a circularly linked list (in C++), let the user fill it and delete nodes from it. When you exit the program, it has to unload from memory node by node. “Empty nodes” are marked with -1 for their values. This drawing I made helped a ton (actually, this was probably the 5th iteration of this drawing).

And here’s another one, this one showing how the heroes in the polymorphism project either rejoin the tournament queue or get kicked out to each player’s respective loser pile.

PS: Some people got really precious about their diagrams having to be works of art, but you don’t have to for these assignments. Just draw this stuff out, paper/pencil (or a little whiteboard) is sufficient, and plan to trash your first few drawings. If you need some material to bulk out your retrospective writing assignments for each project, photos of the diagrams you make are excellent fodder.

Go straight to Google (and Stack Overflow, and YouTube)

Sure, it sucks to pay $1880 to do so much self-teaching but you’ll get a lot of mileage out of the skill. The recorded lectures are crappy and I felt like they were wasting my time. There are better guides to all of the concepts covered in this class on YouTube.

Buy the book

Here’s the book on Amazon: Starting out with C++ Early Objects

I recommend getting a physical copy so you can have it open next to your computer while you work, and use your monitor(s) for your code and Stack Overflow. It’s the same book you use for CS161 (if you haven’t taken that yet, either), so at least you get two classes out of it. You can also buy the loose leaf edition to save some cash.

After two classes with it I can say it’s a good book. The examples are relevant to the coursework, they’re clear and easy to understand, and there are a good number of examples.

Start every week’s material the day it drops – and don’t count on weekends

Sometimes the new week will be released on a Friday. Sometimes a Saturday. Sometimes a Sunday! And no, the instructor doesn’t move that week’s deadline out just because you lost the weekend due to the materials not being released in a timely manner.

For this reason, I recommend setting up your life (at least for these 10 weeks) to allow for working on this class work during the week (ideally daily). Don’t expect to fit it all into the weekend. Even my light weeks were at least 15 hours spent on the class (usually closer to 25 or 30).

Check Piazza religiously

If they improve anything in CS162, I hope it’s the unclear assignment requirements. They requirements were notoriously bad – assignments are written in a conversational style and it’s hard to know what is really being asked for.

Many students took to Piazza (the class forum) to question (or worse, debate) the requirements until a TA or the instructor herself came along to clarify.

Pretty much every week went like this:

  1. New assignment comes out – oh no, it has unclear requirements
  2. Someone asks for clarification on Piazza
  3. TA makes a call and says do it X way
  4. 2 days later, another student asks the same question
  5. Different TA makes a different call on this new thread and says do it Y way
  6. They have a fight, triangle wins…
  7. You already coded it, so do you redo it to Y or keep it as X or what?

For what it’s worth, every time this happened (and I had already coded it), I kept my code the original way and still got 100% on the assignment.

Test on Flip!

So many things happened in my code in the Flip environment that did not happen on my Macbook. Weird things, too – things that weren’t easy to spot without thorough testing. I made the mistake of not testing on Flip until I thought I was done with the assignment, only to find heaps of bugs that only occurred in that environment.

Only after the class ended did I find out about this awesome way to use Git to deploy to Flip. (I was uploading in Filezilla like a n00b.)

Use Valgrind early and often

It’s a memory management tool that’s already installed on Flip and you won’t be able to find memory leaks without it. If you wait until you are done coding your assignment, it will be harder to find the memory leak. Upload your code and check it with Valgrind every so often and you will save yourself a lot of pain.

The worst weeks were weeks 1, 2, and the final project. 

Okay, they were all brutal. There were many weeks where I thought there was no way I would get everything done and I’m a workaholic. The biggest workloads were the first project (Langton’s Ant) and the final project at the end (make an adventure game).

You do actually have to contribute to the Canvas conversation topics

It’s a misguided requirement because these “conversation” threads quickly turn into 100+ people dumping commentary and links in one place. It’s not a conversation, it’s just a dogpile.

But if you contribute a few posts (I think I made 5 decent, paragraph-sized comments between January and March, evenly spaced throughout the quarter), it’s an easy 20 points that you will (probably) be very happy to have at the end.

Take every quiz twice

(Unless you get a great score the first time around, of course).

You get two attempts for each quiz. A quiz is 20 questions in 15 minutes. (I liked this format). Only the grade from the last attempt is kept. Questions are drawn from a larger pool, so you won’t get exactly the same ones the second time you take it.

My strategy was to use the first attempt to see what’s on the quiz and make my best guesses as to the answers. This gave me a feel for the questions and sometimes revealed tricky ones. I usually got about a 16/20 on my first try but Canvas tells you which ones you got wrong, and what the correct answers were, so this is a chance to see what you missed and study it some more. After a little studying I’d retake it, usually getting 18/20 or 19/20 that second time.


The final’s worth 15% of your grade, so save some steam for the end. There was a bonus, extra credit lab announced right at the last minute, too, but its points could only be applied to your lab grade.

  • Weekly labs – 30% of your grade
  • Quizzes – 15% of your grade
  • Projects – 30% of your grade
  • Group activities – 10% of your grade
  • Final project – 15% of your grade

Overall impression: OSU CS162

I hated it at times, but it was worth it. I never would have pushed through some of this stuff on my own, without a grade and a degree motivating me. OSU’s online CS is meant for people with a full-time job and the occasional signs of life outside of class but I had to take a couple days off work here and there to accommodate the workload, and I barely saw my family. The most difficult parts of this class – deciphering confusing and unclear requirements – were totally unnecessary. OSU should hire a proofreader and clean up CS162’s assignments. And some weeks the workload was just pure insanity – the week with the group project stands out in particular.

But… it’s over! And I got a 97%, so I’m going to take a much-deserved week to rest up for the next class.

Onwards to CS225!

Other student reviews of CS162

Leave a comment and I’ll update this post with your review!

Analyzing Amazon Affiliate sales data with MySQL workbench and simple SQL queries

This article is a tutorial for taking Amazon Associates (Amazon Affiliate program) export data into MySQL workbench.

Screenshot 2017-01-21 21.58.25

In MySQL workbench, you can easily view and sort your data in some sophisticated ways that Amazon’s own dashboard doesn’t really support.

I wanted to ask questions like:

  • What was my best-selling item for this particular affiliate ID?
  • What items make the highest commission?
  • Which items get returned the most frequently?

Here’s how I dumped my Amazon Affiliate data into MySQL workbench and some of the queries I used to explore it. I’m pretty new to SQL so I’m sure there are even more sophisticated things I could be doing with this data and different ways to do the same thing!

(You will need to use your own .csv data dump to follow along with this tutorial.) 

Step 1: Get a .csv export of your Amazon Affiliate data

Use the Download Reports button from your Amazon Affiliate dashboard to download your account’s data as a csv (comma separated values). Be sure to adjust the date range.

For this analysis, I exported all of 2016’s Amazon Affiliate data. It’ll generate a bunch of files, but to follow this tutorial you’ll want the file that starts with Fee-Earnings-

Screenshot 2017-01-21 20.11.59

This might take a while, especially if you’re exporting an entire year’s worth of data like I did. You can do the next several steps while you wait.

Step 2: Download and install MySQL workbench

You can download the latest version of MySQL Workbench here.

Step 3: Make a new connection

Screenshot 2017-01-21 13.40.15

Step 4: Start your computer’s MySQL service

You may have to manually start your MySQL server.

On a Mac, it’s in Apple menu > System Preferences… > MySQL

On a Windows computer, these steps might help you.

Screenshot 2017-01-21 13.46.20

Step 5: Create a new schema in MySQL Workbench

Right click in the light blue area underneath SCHEMAS in MySQL Workbench. Choose Create Schema…

Screenshot 2017-01-21 13

Give it a name and leave the rest as-is:

Screenshot 2017-01-21 13.50.21

You should now see the new schema in the SCHEMAS section:

Step 6: Prepare your csv data for import

Your csv file’s first line will cause problems on import, so let’s open the csv and remove it. I used Microsoft Excel for removing the first line but you can probably use anything capable of opening, editing, and saving a csv file (including a basic text editor).

You need to get rid of the first line, the one that starts “Fee-Earnings reports…”

Screenshot 2017-01-21 16.29.24

If you’re saving from Excel (and this problem might be limited to just Excel on a Mac), you should save it as a Microsoft Comma Separated. On my Macbook, at least, saving as a normal .csv from Excel will cause it to fail the import in MySQL Workbench.

Screenshot 2017-01-21 16.53.25

If you have any problems importing the csv file in MySQL Workbench, try different csv formats after saving your csv file from Excel (or whatever you use… I’m convinced my import problems were just a result of using Excel on a Mac.)

Step 7: Bring your csv data into MySQL Workbench

Right-click your schema and choose Table Data Import Wizard.

Screenshot 2017-01-21 14

Follow the prompts and choose your cleaned up .csv file. If everything works, you should end up with a screen like this:

Screenshot 2017-01-21 16.54.49

If you run into any import errors, make sure you’ve 1) removed the first line from the file and 2) saved as a Windows CSV (if you’re saving from Excel, possibly just Excel on a Mac. I don’t have Excel on my Windows computer to test this theory).

Follow the prompts to finish importing the data.

Step 8: SQL queries!

Finally, the fun part!

See the little “circle” made of arrows to the right of the SCHEMAS title? Click that and Tables should refresh and get a roll-out arrow. Click that arrow and you’ll see your data in a table. Right click to select the top 1000 and open the editor.

Screenshot 2017-01-21 16.56.41

Here’s what you should have now: an editor pane and a bunch of results below.


Each query starts with a SELECT and ends with a semicolon (“;”). To run just one query, place your editor cursor anywhere inside the query and click the lighting bolt with a cursor icon.

Screenshot 2017-01-21 20.40.39

Here are some queries I developed for analyzing my Amazon Affiliate data. Feel free to steal them, modify them, and use them to analyze your own affiliate sales data.

Select all the items sold for a particular tracking ID

This one’s straightforward: it selects all the items sold under a particular tracking ID. Most of my more sophisticated queries are built on this one, and it’s a good way to narrow down your data if you have multiple IDs.

SELECT * FROM amzn2016_schema.data 
WHERE `Tracking ID` = "yourtrackingidhere-20";

See which items earned the most money (“fees”) for a particular affiliate ID

SQL comments start with a #, so they’re handy for adding notes to your queries. This query selects all the items for a particular ID that earned me $5 or more, with the highest earning items at the top of the list.

#just the most profitable items from that ID
SELECT * FROM amzn2016_schema.data 
WHERE `Tracking ID` = "yourtrackingidhere-20" 
AND `Ad Fees($)` >= 5
ORDER BY `Ad Fees($)` DESC;

See which items were your most frequently returned

Here’s something Amazon doesn’t make easy to figure out in their dashboard: which items you sold that got returned, and in what quantities.

This query tells you the names and tracking IDs of the items that had return counts, with the highest at the top.

#most returned items
SELECT `Tracking ID`, `Name`, floor(SUM(`Returns`)) as `Return count` 
FROM amzn2016_schema.data
ORDER BY `Return count` DESC;

See which items earn $15 or more per sale

What items earned you the largest commissions? This query will tell you.

You can change the 15 to whatever you want your bottom to be – for me, earning $15 on a single sale is super awesome so I wanted a list of just the items that earn $15 or more per sale. Who knows, I might find a new product to write about by digging around this list!

#items with ad fees over $15
SELECT * FROM amzn2016_schema.data 
WHERE `Ad Fees($)` >= 15 
AND `Items Shipped` = 1 
ORDER BY `Ad Fees($)` DESC;

I set it to only return items that have 1 item shipped, otherwise I get groups of items and artificially inflated Ad Fees as a result. However, since some items have only been purchased in sets of multiples, it’s a good idea to change this number to a 2, 3, or more (or remove the line altogether) to see those items, too. 

Sure enough, I found some items that earned me some large commissions – $44.93, $39.75, and $36 off of these single items! These aren’t items I blog about, but… maybe they should be now that I know about them! :)


Find your most expensive item sold through Amazon Affiliate program

That got me wondering: what’s the most expensive item someone has bought through one of my Amazon Affiliate links?

This query made it easy to figure that out:

#most expensive item sold
set @maxPrice = (select MAX(`Price($)`) FROM amzn2016_schema.data);
SELECT * FROM amzn2016_schema.data WHERE `Price($)` = @maxPrice;

My most expensive item sold is one of those sweet Wacom tablet computers! Cool!


Notice how the ad fees (my earnings from selling this item) are capped at just $25, despite its high sales price? That’s the nature of Amazon Affiliate program – some items, even though they sell for a lot, don’t always earn a proportional amount in ad fees. (Some items that cost much less than this tablet computer actually bring in higher ad fees.)

See earnings and items sold, by affiliate ID

Here’s another fun bit of data, especially if you have multiple sites or multiple IDs for a single site and want to compare them all. This query outputs each affiliate ID, how many items it sold total, and how much money it earned.

#all IDs and how much they made, grouped by ID
SELECT `Tracking ID`, floor(SUM(`Ad Fees($)`))
as `Fees earned`, COUNT(*) as `Total items sold`
FROM amzn2016_schema.data 
GROUP BY `Tracking ID` 
ORDER BY `Fees earned` DESC;

Find your best-selling items and how much they earned (collectively)

If you’ve ever wanted to know what your best-selling items are across all your Amazon Affiliate IDs and how much you earned from those items, here you go:

#best-selling items by tracking id with fees earned as a total 
SELECT `Tracking ID`, `Name`, 
COUNT(`Name`) AS `number sold`, 
floor(SUM(`Ad Fees($)`)) AS `earnings`
FROM amzn2016_schema.data
ORDER BY `earnings` DESC;

That’s it for now! I hope you found these queries useful for analyzing your Amazon Affiliate sales data.


Passing a 2D array to a function in C++ as an array or pointer

I recently had an opportunity to experience the joys of passing 2D arrays (both as themselves and as pointers) to functions in C++.

Both of my examples here assume you already know the size of your 2D array (3×3, in this case).

int array[3][3] = {{0,0,0},{0,0,0},{0,0,0}};

Passing a 2D array to a function in C++

Notice the empty first set of brackets. For some reason, C++ only needs to know the columns. It can figure out the rows on its own (though it won’t break if you do include the row size).

int array[3][3];

void doStuff(int arr[][3]) {
   //accessing stuff inside it
   int someCellData = arr[0][0];


Passing a pointer to a 2D array to a function in C++

int (*p_array)[3][3] = &array;

void doStuff(int (*arr)[3][3]) {
    //accessing stuff inside it
    int someCellData = (*arr)[0][0];
doStuff(p_array); //notice you pass it without the *

Additional notes on passing a pointer to a 2D array to a function in C++

When you declare and define the pointer to the array, you have to include the rows and columns sizes in accompanying square brackets.

If you don’t, you’ll get this error on that pointer’s definition line when you compile:

cannot initialize a variable of type 'int (*)' with an rvalue of type 'int (*)[3][3]'

So, don’t define your pointer to your 2D array like this:

int (*p_array) = &array; //wrong!

Do it like this:

int (*p_array)[3][3] = &array; //include rows & columns

More reading

These Stack Overflow queries helped me figure this out:

OSU eCampus CS161 Intro to Computer Science review & recap

This post is part of an ongoing series recapping my experience in Oregon State University’s eCampus (online) post-baccalaureate Computer Science degree program. You can learn more about the program here.

With my successful completion of CS161, I am now 1/16th of the way to a Computer Science degree! Despite being labeled an “intro to CS” course, this class wasn’t a walk in the park – the two exams (worth 60% of the grade) were the tough part.

CS161 syllabus, topics

My CS161 was taught by Tim Alcon. He was remarkably responsive on the class forum (“Piazza”) and over email. There were something like 200+ students in the class, though, so assignment grading was done by a group of teacher assistants (TAs).

Syllabus: CS161 syllabus

Topics covered:

  • Introduction to C++ language
  • variables
  • methods
  • arrays
  • passing data into methods
  • data types
  • while loops, for loops
  • memory management (introduction)
  • pointers
  • object-oriented program structure
  • good coding style (comments, naming)

If you’re a prospective student reading this and these topics are all brand new to you, you should get familiar with them prior to the class. The class moves pretty quickly, especially past week 3.

These are all courses/video series I’ve worked through myself and recommend to anyone wanting to get started with programming:

CS161 class format

The course is 10 weeks long. Every Wednesday at midnight the next week’s homework and reading (called a “module”) becomes unlocked in the class portal (known as “Canvas”). You can do the reading/homework as fast or as slow as you want, as long as it’s turned in by the due date, typically the next Sunday or Wednesday (so you had either 5 or 7 days to get everything done before the next batch opened up). There weren’t any videos or supplementary materials beyond the book. Basically it’s read the chapter, do the homework, repeat. 

Early in the course, I found this drip-feed of content frustratingly slow. I wanted to work ahead and take advantage of free time when I had it. I usually had my assignments done within a day of their release. After about the halfway point, though, the class picked up the pace and I was turning in homework much closer to the Wednesday night deadline.

CS161 homework assignments

Every week had a reading assignment (usually 1-2 chapters from Starting out With C++: Early Objects) and a coding assignment. Some weeks also had a group assignment and/or a reflection assignment (1-2 pages written response). For the code assignments, you upload .cpp files to upload via “TEACH” (OSU’s interface for uploading homework).

The time commitment was reasonable, in my opinion. My daughter was born the same day class started so I had the advantage of being on maternity leave from work, but a newborn is demanding and I ended up squeezing homework and reading in anywhere I could, at odd hours of the day. In the early weeks of the class I spent about 4-5 hours a week on reading and homework combined. In the later weeks, I was spending 8-10 hours per week on the reading and homework combined. However, it’s worth adding that I’ve worked as a programmer (front end web developer) for the last 2 years, have already completed a web dev bootcamp, and have put myself through various online self-paced CS courses (this one just happens to be worth a college credit).

I thought the assignments were clear in their requirements and it was easy to understand what I needed to do.

The course materials suggest that you need a Windows machine and Visual Studio for CS161, but that’s not necessary – I did a lot of my homework on my Macbook and I never opened Visual Studio on my Windows machine. On my Windows computer, I used MinGW as my C++ compiler and wrote my code in Sublime Text. With this setup, I didn’t have to worry about Visual Studio adding anything extra to my files and my homework always compiled on Flip, the school’s Linux environment that you can log into and upload your project files to for testing. (This is the same environment the TA’s use to check if your work compiles.)

Some weeks had group assignments, which were coordinated over the Discussion groups in Canvas. The two major group assignments were basically “everyone upload last week’s homework, then decide amongst yourselves which one is best and write a page explaining why you picked it”. I found my classmates responsive and eager to complete the assignment; this wasn’t the group assignment horror-show you might remember from high school, at least not here in CS161 where it wasn’t about producing a completed project together.

Assignments were usually graded about a week or so after turning them in. Feedback was a line, at most, usually “Looks good!” or “You didn’t give this method the right name, -2 points”.


CS161 exams

The most important thing to understand about OSU CS eCampus exams is that they are “proctored”, which is academia-speak for “supervised”. This was my first experience with proctored exams. (And this will be the case of all exams for the online CS degree program, not just CS161.)

There are two proctoring options:

  • Take it in person at a local university/college/community college/test center (this is what I did)
  • Take it at your own computer with a live webcam stream of your face running the whole time with a service like ProctorU

I thought the ProctorU option was creepy as hell, plus I couldn’t guarantee the people I live with would actually be quiet while I took the exam. They require a 360 view of the room you’re in before you start, and any interruption is grounds for your test to be disqualified. Getting up to yell at someone / deal with a fire / etc is enough to make the person supervising you over ProctorU disqualify your test. Reading others’ first-hand experiences with ProctorU also put me off the service pretty quickly, but I never actually tried it myself.

Taking the exams at my local community college’s test center was easy once I confirmed with them that they were approved for OSU tests. I scheduled a time (they even had Saturday hours), showed up, sat down at a computer, logged into my OSU Canvas account, and started the test. The test is timed, and the test center provides paper and pencil (which they keep after the exam). The test runs in your web browser. My local test center charged $35 per test.

As for the exams themselves, I found them rather tricky. Each of the exams (there are 2) are 20 multiple choice questions with 4-5 answers to pick from. You have to hand-trace through the code (which is often iterative) and spot any errors that might be included in the code. (The paper and pencil help a lot here.)

In real life, you get the help of a compiler and unit tests (that I’m sure you wrote because you’re a good programmer) to help you understand (or debug) a bit of code, so the tests felt unnecessarily difficult and unlike my professional coding experience.

Here’s an example. One exam question had something like this (embedded in a much larger block of code):

if (x = 3) {
   ...stuff here...

I caught the single = sign, but I didn’t know it would actually do something in this case. In C++ (and other languages), this evaluates to true and sets x to 3. I’m just citing this as an example of how you have to know the fiddly bits of C++ to really excel at the exams. (I managed an 80% and an 85% on the exams.)

The test is graded as soon as you submit it, but you won’t know which ones you got wrong until they unlock the tests a few weeks after they’re done. Furthermore, while they’ll eventually tell you which questions you got wrong, they won’t tell you what the correct answer was.


So, don’t expect the exams to be much of a learning experience until the course has ended and you can work through the questions with an IDE and compiler.

Overall impression: OSU CS161

OSU’s eCampus Computer Science program looks solid from here, and I thought CS161 was a good value. The materials were well put together, the pacing was reasonably challenging, and the course’s time demands seem manageable for someone with a full-time job and family (I was on maternity leave while I took the course). I came into the class with more prior experience than the class is really meant for, but I still felt satisfied and challenged by the material. The OSU eCampus Reddit forum is a helpful resource for information on individual classes, admission process, instructor reviews, etc.

Onwards to CS162!

Review: Starting Out With C++: Early Objects, Student Value Edition (9th Edition) book

I got into Oregon State University’s post-bacc computer science degree program! Fall quarter begins September 21st, 2016 and I’m excited to start. (More on that later!)

This post, however, is about the book I needed for the first class, CS 161. The book, “Starting Out With C++: Early Objects (9th Edition)”, is available on Amazon, but it is expensive. And it has a 1-2 week processing wait.

That wasn’t gonna cut it – class starts next week.


I wanted a real dead tree book, not an ebook, and I live too far from OSU to “rent” the book from their bookstore for the quarter. My search led me to something called the “Student Value Edition” of Starting out with C++: Early Objects”.

The “Student Value Edition” is significantly cheaper than the usual version. But it had no reviews, and I couldn’t find anyone else talking about it online, so I was kind of hesitant to order it.

(I ordered it anyway.)

I’m happy to report that this book is the real deal.


It arrived 3 days after I ordered it. It’s basically an unbound stack of papers 1.5 inches thick. Nothing holds it together except for the plastic sleeve it arrives in.

Other than that, though, it’s exactly the same content you’d get with an actual binding and cover. It’s in color, printed on both sides, and the individual pages are thin(ish) but probably no thinner than what’s in the actual book.


An inexpensive 2″ slant-ring binder like this one solved the lack of binding problem.


And there you have it – a slightly more affordable way to get CS 161’s book in paper format.

As for the book’s actual content, I’ll be working through it over the next 11 weeks and I’ll let you all know what I think. I’ve read the first two chapters and it looks like it’ll be a solid introduction to computer science fundamentals textbook.

If you’re starting CS161 soon and want to save some money on the book, check out the “Student Value Edition” of Starting out with C++: Early Objects”.

How to see an app’s jQuery version in browser console (Chrome)

Recently, I was working through a dependency conflict in an Ember app. I needed to verify which version of jQuery was in use by the app to see if it matched what I expected it to be using.

Complicating things was the fact that the Ember app in question uses a proprietary UI element library (like Bootstrap, but specific to the company developing the app) that has its own version of jQuery.

In your browser’s console (I did this on Chrome), use this to see the page’s jQuery version:


And use this to see the version of jQuery in use by your app’s version of Ember:


Why are the versions different?

As far as I can tell, it’s because in my case the “vanilla” jQuery was coming from the UI library, and the Ember version of jQuery was the one defined in my Ember app’s bower.json file.

There isn’t more to this story; it’s just a useful set of commands that might save someone else some digging.

Ember: Using queryParams to distinguish “editing a record” from “making a new record” on a route

This guide uses Ember 1.13


The concept is simple and familiar: you have a page (“route”) in your Ember app that you want to use to either enter new data or modify existing data on the same record.

Example: your user is presented with a blank form to enter their shipping address.  The user enters their info and submits it (thus creating a new record). When your user goes to edit their saved shipping address, that same form is populated with their existing shipping information (loading a record). The user edits, saves, and the updated record is persisted.

One form, two behaviors (new and edit). 

This, like many things in Ember, was surprisingly painful to get working. I found queryParams to be a good solution, but the documentation on queryParams was difficult for this beginner to understand and it contains (what I think is) at least one mistake that held me up for a long time while I figured it out.

It didn’t take much code to get this working, just a lot of guessing and trying, so I thought I’d add my knowledge to the (vast, mostly out-of-date now that it’s 2016) library of Ember queryParms knowledge out there on the internet. Hopefully this helps someone.

About this tutorial

In this guide, I’m going to show you how I used queryParams in Ember to distinguish the “new” state from the “edit” state on the same route (“basics”).

About the example app

This guide uses my Ember app, “Classis”, for many of its examples, which you can explore in full on Github (it’s a work in progress but the queryParams part is done on the “basics” route if you want to look at the app that inspired this post).

“Classis” is a (fake) web app where people sell “seats” in classes they teach: tutoring, dog training, etc. It’s a lot like listing a room on AirBnB, dog boarding on Rover.com, etc. Think of classes as products people are selling, and you’ve got the idea. I call refer to “classes” as “products” in this tutorial to cut down on confusion with the programming concept, but they are called classes in my app. 

About queryParams in the context of editing records

You can use queryParams for lots of things. This particular guide shows you how to use them for editing records that have ids.

If the user is trying to edit an existing record, we can get its id and pass it along to the route where the user will edit that record. If the route sees you gave it the id, it will behave differently.

The “I’m making a new one” url looks like this:


The “hey, I’m editing a specific one” url looks like this:


Pass the queryParam from somewhere

There are lots of ways to pass a queryParam around, but in my case, I needed to pass it from an “Edit” button contained within a “class-card” component. That component’s job is to display a user’s completed product, and one “class-card” is displayed for each product the user has. Product data is passed into a class-card, and that product data includes the id.

Basically, I have a product with an id. The component knows about the product’s data, including its id. I want to pass that id to the basics page where I will edit the basic info about a product.

(I simplified the styling classes in this example and bolded the relevant part)


{{#link-to 'basics' (query-params id=class.id) class="mdl-button"}}

Now the class id (product id) will get sent to the ‘basics’ route.

You can also pass queryParams on a transition in, say, an action. Here’s a hypothetical action method I made just for this post, it’s not in my app anywhere but I included it here in case you need to pass a queryParam from an action:

goToBasics() {
  const route = this;
  const id = this.controller.get('id') || '';
  route.replaceWith('basics', {queryParams: {id: id}});

Define the queryParam on the “parent” controller

There are many ways to structure an Ember app, and I can’t claim to know them all. I do know, however, that my app uses application.js as its parent controller, so this is where I defined queryParams.

That definition looks like:


import Ember from 'ember';

export default Ember.Controller.extend({
 queryParams: ['id']

On a complex app, you might bury this deeper down inside the app, so that (perhaps) user ids don’t get confused with product ids or whatever, but on this simple app, the parent-most parent can handle it.

Add the queryParam to the route in router.js

All of my app’s routes are defined in app/router.js.  ‘basics’ is the route that you can pass an id to to distinguish “new” from “editing”.

Contrast with location/:id, which treats id as a dynamic segment (link goes to Ember documentation on the subject).

I included this here to illustrate the difference, because it’s easy to confuse the two (like I did when I was getting started with this stuff).


Router.map(function() {
  this.route('basics', {queryParams: 'id'}); //queryParam
  this.route('location', {path: 'location/:id'}); //dynamic segment

Url with a query param looks like:


Url with a dynamic id segment looks like:


Long explanation of why I did it this way:

In my app, the user goes from basics to location, in that order. Basics is the first page the user encounters. It can be used to either create a new record or edit an existing. Location, by contrast, is always used to edit a record that exists, because that record was created by basics, the page before it. If you’re on /location, it’s because you are making changes to a record that has already been created, even if you’re entering location data for the first time.

In Ember, having some understanding of what order pages are encountered in can help you make these sorts of architectural decisions (at least, until your designer decides location should come first, then you get to change this stuff or maybe handle everything with a queryParam in the first place, or whatever makes sense for your app).

Add the queryParam to the route itself

Basics is where the user edits “name” and “description” of an individual product.

Inside Route.extend, define the queryParms object like so:


export default Ember.Route.extend({
  queryParams: {
    id: {refreshModel: true}

Now /basics knows that it might sometimes get passed an id, and if it does, it should refresh its model.

Get the queryParams inside the model

!!This part was hard to figure out!!

Ember’s documentation just shows one parameter passed into model, but try as I might, param just came in as a useless empty { } object. I could see my queryParam in the url, but I couldn’t get at it from param.

After much Googling, I found the answer: the queryParams are on the second parameter accessed by model, which you can name transition:

(still in) routes/basics.js (right below the queryParams object you just made)

//queryParams are contained inside transition, which has to be passed as    the 2nd parameter to model

  model(param, transition) {
    let id = transition.queryParams.id;
    if (id) {
      return this.store.peekRecord('class', id);


I’m not sure if it’s my Ember newbieness or an actual oversight in the 1.13 documentation, but model(…) {…} totally takes more than one parameter and the second one contains that sweet, sweet queryParam you passed in.

The code in my example above looks at transition, sees if it contains an id, and if it has an id, it gets the matching ‘class’ record out of the store.

A lot of Ember tutorials perpetuate the idea that if you do model(param), the queryParam will be accessible on it, so maybe this worked at one point in Ember’s history or I just set it up wrong in mine.

Curiously enough, the guide to model hooks that enlightened me to the transition parameter also says there’s a third parameter for model straight up called “queryParams”(!!!), but in my case, that third parameter comes in empty. Only the second parameter (transition) had anything useful. I cannot explain this, I’m just reporting it in case it’s useful to someone else. (Maybe someday I will understand all of Ember’s mysteries.)

Load existing record data in setupController (but only if it exists)

Almost there: let’s load that model data into the controller now that we have it.

(still in) routes/basics.js (below the model method) 

setupController(controller, model) {
  let application = this.controllerFor('application');
  application.set('pageTitle', 'Basics');

  if (model) {
    //we're editing an existing class
    this.controller.set('existingClass', model);
    this.controller.set('editingExisting', true);
    this.controller.set('title', model.get('title'));
    this.controller.set('description', model.get('description'));
  } else {
    //this is a new class
    this.controller.set('title', '');
    this.controller.set('description', '');

Now, when we visit /basics with a queryParam in our URL, we’ll see our product’s title and description! If we visit /basics without a queryParam, title and description will be empty.

We are almost done…

Update the existing Ember record if we’re editing an existing one, create a new record if it’s a new one

Finally, we need to tell our route what to do when continuing past this page. If we have a queryParam, we want to update that record and move on to /location. If we don’t have a queryParam, we want to make a new record and move on to /location.

routes/basics.js (in the action hash now) 

actions: {

  transitionToNext(newClass) {
    console.log("going to location");
    this.replaceWith('location', newClass);

  failure() {

  continue() {

    //editing an existing class
    if (this.controller.get('editingExisting')) {
      let existingClass = this.controller.get('existingClass');
      existingClass.set('title', this.controller.get('title'));
      existingClass.set('description', this.controller.get('description'));

      existingClass.save().then(() => {
        //go to location and pass along the this existing class's id
        this.replaceWith('location', existingClass.get('id'));

  } else {

    //making a new class
    var newClass = this.store.createRecord('class', {
      title: this.controller.get('title'),
      description: this.controller.get('description')

    newClass.save().then(() => {
      //pass along the newly created class's id
      this.replaceWith('location', newClass.get('id'));

It’s the biggest block of code in this guide but it’s straightforward: if you have the editingExisting flag set in the setupController, set the updates and move onto location. If you don’t have this flag, make a new record.

Debugging advice

If you get stuck, remember you can look in the Ember Inspector to see if your records actually exist and confirm that they have the IDs you expect.


You can also console log the id at various points in your code to see if it’s coming where you expect it to.

You can also display the id in the template, which I found helpful in confirming that what I was seeing was indeed, what I was getting, like so:


I click EDIT and that same ID is now in the url:


That’s it!

This post was inspired by my work on a personal project I keep publicly available here on github – check it out if you’re new to Ember and want to see a relatively simple Ember app demonstrating queryParams and other concepts.

Ember: Making a set of radio buttons that change a value set on the controller

This guide was written for Ember 1.13


So, Ember doesn’t have anything in the way of built-in radio buttons, but there’s a great add-on called ember-radio-button, which you can install via ember-cli:

ember install ember-radio-button

In this particular tutorial, we’ll use ember-radio-button to set up two radio buttons that work as a pair (so only one can be “on” at a time) and set a variable on your controller based on which one the user picks. We will also set one of the radio buttons to be on by default.

Like this:


This guide assumes you already have a template (yourpage.hbs) and a corresponding route (yourpage.js) to work in.

In Ember, adding your code to templates and routes is kind of chicken-and-eggy (where to start?), but I tend to start in the template (.hbs) file.

In your route’s .hbs file

Use the {{#radio-button}} label {{/radio-button}} syntax if you want labels for your radio buttons (which you probably do).

This will give you two side-by-side radio buttons:


  • value is what will get automagically passed to the controller when you click this radio button
  • groupValue should match across all radio buttons in the set, or your radio buttons won’t know to un-select themselves when you click a different one
  • changed is the action method called when this radio button is clicked

When the user clicks one of these radio buttons, flavorToggled(choice) will be called and the value passed to it as choice will be “vanilla” or “chocolate”.

In your route’s .js file

Add a new action to your action hash. You can call “choice” anything you want (or omit it entirely if you don’t need a passed-in value for whatever reason).

The value that gets passed in here as “choice” was taken from the radio button’s “value” property.

actions: {
  flavorToggled(choice) {
    console.log("changing flavor choice", choice);
    this.controller.set('flavor', choice);

If you want one of these radio buttons to be checked by default, you can do that in the setupController in your .js file like so:

setupController() {
  this.controller.set('flavor', "vanilla");

All done!

That’s all there is to it! The documentation that comes with ember-radio-button shows a few more things this tutorial did not cover. Thanks, yapplabs!


Ember: Making a button component that calls an action

This guide uses Ember version 1.13.


I recently started a new Ember 1.13 app to explore Google’s Material Design Lite style library. I use Ember in my day job, too, and something that has always stuck out to me as “should be easy but isn’t” in Ember is making a button component that calls an action. 

I wanted a “continue button” component that…

  • can be re-used throughout my app
  • calls an action customized per route (ie: the continue button on the ‘basics’ route goes to the ‘location’ route, the continue button on the ‘location’ route goes to the ‘students’ route, etc)

This was surprisingly unintuitive in Ember. I expected to pass an action into the component from the parent template and have the component know where to find that action.

What not to do

I think many people who try to put an action on a component start with something like this. Note that this approach doesn’t actually work:


{{bad-example-button action=”wontWork”}}


actions: {
  wontWork() {
    console.log("you'll never see this!");

What’s missing? The call to the route’s action has to come from the component itself.

The rest of this guide will show you what does work for getting a component to fire an action on the parent’s route in Ember.

Generating the button component

Do this step inside your Ember project directory (assuming you are using ember-cli):

ember generate component continue-button

In the route’s template

First, add the component into your .hbs template. The action it calls, “continue”, needs to be defined in the action hash in this route’s .js file.


{{continue-button actionToCall="continue"}}

In the route’s js file

In your route’s .js file, create an action hash if you don’t have one already (actions: {…}) and put a “continue” method inside it. I like to stick a console log in here, too, on the first try so I have something to look for in Chrome to confirm it’s working.


actions: {
  continue() {
    console.log("continuing on to location page");

Code for the button component

When you generated the button component you got an .hbs template file and a .js file.


The important piece here is that the <button> tag contains {{action “doButtonThing”}}.

<button {{action "doButtonThing"}} class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">Continue</button>


doButtonThing is an action on the component’s own action hash. When you call doButtonThing, it’s going to fire a sendAction that references the actionToCall defined up on the component in the route template.

import Ember from 'ember';

export default Ember.Component.extend({
  actions: {
    doButtonThing() {

Yes, this is confusing as #$*! and I’ve not seen a better way to do this in my year or so of developing in Ember. It feels very much like a child (the component’s .js) is telling a parent (the route’s .js) what to do.

Another way to think of it

The {{continue-button …}} up in basics.hbs knows what to do when clicked (call “continue” action in basics.js) but it’s not going to do it until told to do it. It sits around listening for the “fire!” command.

When the user clicks the button, the code on the button component itself has its own action to call. That action yells “fire!” to the instance of the button waiting up there on the route. The {{continue-button …}} up in basics.hbs hears the fire command, delivered from the component itself in the form of a send-action.

There is no “passing” of an action into the component, it’s more like a pairing of broadcaster and listener. 

The Ember community calls the larger concept at work here “data down, actions up” which took me a while to internalize. You can read more about DDAU here.

What to change in MaxCDN settings after you change web hosts

I just moved one of my blogs to a new host (yay!). This blog uses MaxCDN for its content delivery, and moving the blog to a new host messed up the site’s styles and it took me a while (plus some back and forth with support) to get everything fixed because MaxCDN was still referencing the old host.


In case I ever do this again, here’s what needed to be done to move my WordPress blog to a new host with MaxCDN as my content delivery network.

Step 1: Add a CNAME record to your new host

My new host has CPanel (Digital Ocean, by contrast, had a Networking tab with a link to Domains and their records were accessible through there). If you have CPanel, click on Simple DNS Zone Editor.

Add a new CNAME record. It’ll probably look something like this:



(Your CPanel might add the . at the end of name for you, and it might autocomplete for you if you just type the subdomain portion and then tab out of the field.)

MaxCDN has good documentation on updating CNAME records for a variety of hosts, too.

Note: I use a custom domain in MaxCDN because I don’t want it to use the default “business name” URL that MaxCDn gives you.

Step 2: Update the Origin IP over in MaxCDN’s settings for your pull zone

Go to Zones > Pull Zones > Settings and get into that particular pull zone’s settings. At the bottom is Origin Information. Check the checkbox and enter the IP address for your new host. Click Update button to save.

Step 3: Whitelist your new IP

Go into your Account > look under the API section > click Manage > add your new IP as a whitelist IP.

You may also need to whitelist your own IP address, if you get problems with cURL requests failing when you try to clear CDN cache.

Step 4: Update your WP caching plugin

You may need to reconfigure your WP cache plugin. I use W3 Total Cache which, for reasons unbeknownst to me, likes to replace my entry for “Replace site’s hostname with:” with the word “Array” instead of the URL I give it.

For reference, “Replace site’s hostname with:” should be followed by your cdn url, like cdn1.yoursite.com.

Step 5: Purge all caches and check your site

When you’ve done all of the above, purge your CDN cache and your WP cache via your caching plugin.

It might also help to flush your local DNS. I’m on Windows and I do that in a command prompt with ipconfig /flushdns

Open a Chrome incognito tab and load your site – if your styles and images load, you’re good to go. If your site looks incomplete, look in the console for an error message. I found many of them (like 502 bad gateway) to be covered in MaxCDN’s documentation.

More tools for debugging DNS, caching issues

If you’re having problems, try these tools:

Did it propagate yet? Whatsmydns.net is a great way to check propagation and see what is actually getting served when you try to hit your CDN’s URL.

If you are using a custom domain with MaxCDN like I am, then putting that custom domain into whatsmydns should yield the actual “business” domain in the results list. In other words, if you search for cdn1.yourcustomdomain.com and you get responses of cdn1.yourbusiness.netdna-cdn.com, you’ve got it set up correctly.

What’s your site’s IP? In a command prompt / Terminal window, ping yoursite.com to get its IP address.

Is your CDN URL responding? In a command prompt / Terminal window, ping cdn1.yourcustomdomain.com and see if you get anything. If it can’t find your host, this could indicate an error with your CNAME record with your new hosting service.

Are you seeing stale or current stuff in your browser? I use Chrome incognito because each window starts with a fresh cache and no cookies. CTRL SHIFT N opens up a new incognito window.

You may also want to flush your DNS in between tests. ipconfig /flushdns does this in Windows.

If all else fails, email MaxCDN’s customer support. Even on a US holiday, I got a response within 20 minutes and they helped me get things working again.