Sunday, September 30, 2012

Subscription App

One of the many tedious aspects of the tutoring business is to schedule the groups of students.

Last week I developed a subscription system that collects several data points on the user and then groups them by ensuring compatibility with other users. If a user is not compatible with any of the current groups the system will create a new one.

I tried to make this app as modular as possible. Each data point collected is actually a model and is unrelated to the other models. Each model has a method called compatible?( model ). The parameter it takes is another model of its own class. It then compares the models and returns true if they are compatible. Comparing two users compares all their sub models for compatibility. Comparing a user to a group compares that user to all the users in the group.

If we want to add more data then we just need to add another model, write its compatibility method, and make the user compatibility check use it.

Tutor Interface

This week I spent some time redesigning the tutor side of system.

Nothing major, just making it cleaner.

Vocab App

Last week I developed an API to enable a client to connect to the system and pull a list of words and their definitions. The client program then runs a game and saves the results in the system.

I also wrote some ruby scripts to input the words and definitions into the system, also using the api.

require 'net/http'
require 'json'
require 'csv'

class Poster

  def initialize
  @words = URI('http://URL GOES HERE/words.json')
  @definitions = URI('http://URL GOES HERE/definitions.json')
  end

  def post_word name, difficulty
    res = Net::HTTP.post_form(@words,'word[name]' => name.encode('UTF-8'), 'word[difficulty]' => difficulty.encode('UTF-8'))
    JSON.parse(res.body)['id']
  end

  def post_definition word, body
    res = Net::HTTP.post_form(@definitions,'definition[word_id]' => word, 'definition[body]' => body.encode('UTF-8'))
    puts res.body
  end


end
poster = Poster.new

CSV.foreach(ARGV[0], {:headers => true, :header_converters => :symbol, :col_sep => "\t" }) do |row|
  poster.post_definition(poster.post_word(row[1],row[0]),row[2])
end


The Program goes through a CSV file that has the words, their definitions and their difficulty. It posts a word to the system and gets back a word_id, then it posts the definition passing it the corresponding word_id

Tuesday, September 18, 2012

Weekend update

This weekend I made several updates to the system.
  • created scaffold and api for vocabulary review game
  • created a view to export content data (questions and categorization data) data as a CSV file
This took me a while because I could not get the CSV file to be parsed correctly. Question text contained commas so I could not use that as the delimiter. Instead I used tabs. The other problem I had was that there existed \n and \r characters in the question text. To fix this I found some code that effectively cleansed the string. This was the final version:

<%= v.to_s.squeeze(' ').strip.chomp.gsub("\r","").gsub("\n", "")  + "\t" %>



  • added a parent method to the stat model which returns the parent of the associated 
  • created a way to collect and pull aggregated data from individual users
This week I will be working on the tutor interface.

Sunday, September 16, 2012

Content API

Due to the fact that we are a start up company we need to be exploring different sources of traffic and revenue. Because of this we might have a separate group working on game development and mobile applications. However these apps will need to interact with the system to pull data. For example, the apps themselves will not store any content data but rather request it from the system through an API. User data will also be stored through the system. This not only creates a centralized place for data but also enables authorized third party developers to interact with the system without replicating data or making changes to production code.

The API will enable developers to pull question data, create assignments, save user data including answers and generate and pull statistics. All this will be accessed using a standard REST API format.

Tutors and Assignments

Its been a long time since I've looked at the tutor side of the system. This week I created a bunch of methods that together enable the tutor create exams based on certain criteria. For example, a Tutor can now select a category, average difficulty, amount of questions and target user and the system will create and assign an exam.

This is essential to the tutoring side of the business because its going to cut time on the tutor side and enable one tutor to serve more students.

Besides an assignment gun I also need to implement a way for students to be assigned to a tutor. At the moment the users need to be manually added to a Group and groups need to be assigned to a specific tutor. Ideally I would want either a algorithm to auto assign the students to a group based on certain criteria or a front end that will allow the tutors or an admin to assign students to groups and manage tutors.

Wednesday, September 12, 2012

Abstraction and Polymorphism

Today I was working on the stats generation for the homeworks and I noticed that it took a ridiculous amount of time to pull the aggregated stats for any user.

The problem seemed to be that I had to run a bunch of sql calls in order to get the information to build each Stats block. It seemed unreasonable that I would have to compute this on the fly whenever the user requested it. I cannot loop over all the user's answers every time they want to see their stats.

To solve this I decided to create a new Stat model and use polymorphism to deal with the different elements that would need statistics.

For each question we have several data points that we collect and they have a heirarchy. These are considered to be Statable (polymorphism)
After each exam the the data points from the questions are collected and computed into the "stats". Then a new entry in the Stats table is created with all this information. Here I will take advantage of the queue system in heroku and send these data computing jobs to run there.

Now with this new setup I can pull aggregate data easily by running a simple sql query. More importantly I also now have data for specific time periods. It would have been much harder to see progression over time of a particular user because I would have needed to use the dates on the exams. Now I just get the stats from a range of dates and I can even filter it to specific data points.