diff --git a/.hgignore b/.hgignore index 41ed3d8..041f497 100644 --- a/.hgignore +++ b/.hgignore @@ -1,2 +1,4 @@ \.pyc$ \.zip$ +\.swp$ +mmg diff --git a/README.md b/README.md new file mode 100644 index 0000000..0f578a5 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# mmg.mcquay.me + +## background + +This is a silly little go project that I created to help my child learn his +addition/subtraction tables. diff --git a/README.rst b/README.rst deleted file mode 100644 index 3323410..0000000 --- a/README.rst +++ /dev/null @@ -1,9 +0,0 @@ -============= -mmg.mcquay.me -============= - -background -========== - -This is a silly little django project that I created to help my child learn his -addition/subtraction tables. diff --git a/handlers.go b/handlers.go new file mode 100644 index 0000000..c8591bc --- /dev/null +++ b/handlers.go @@ -0,0 +1,123 @@ +package main + +import ( + "encoding/json" + "fmt" + "github.com/gorilla/sessions" + "log" + "math/rand" + "net/http" + "strconv" +) + +type prob struct { + Operation string + First int + Second int + Score int +} + +type solution struct { + Status bool + Score int +} + +type JsonHandler func(http.ResponseWriter, *http.Request) + +func (h JsonHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + w.Header().Set("Content-Type", "application/json") + h(w, req) +} + +func getScore(session *sessions.Session) int { + score := session.Values["Score"] + var parsed_score int + if score == nil { + parsed_score = 0 + } else { + parsed_score = score.(int) + } + return parsed_score +} + +func problem(w http.ResponseWriter, req *http.Request) { + operation := "+" + if r := rand.Intn(2); r == 0 { + operation = "-" + } + + first := rand.Intn(MAX) + var second int + if operation == "-" { + if first == 0 { + second = 0 + } else { + second = rand.Intn(first) + } + } else { + second = rand.Intn(MAX) + } + + session, _ := store.Get(req, "Score") + score := getScore(session) + + r := prob{operation, first, second, score} + + b, err := json.Marshal(r) + if err != nil { + log.Fatal("issue with json marshalling", err) + } + j := string(b) + fmt.Println("problem", j) + fmt.Fprintf(w, j) +} + +func attempt(w http.ResponseWriter, req *http.Request) { + first, err := strconv.Atoi(req.FormValue("first")) + if err != nil { + log.Fatal("cannot parse first", err) + } + + operation := req.FormValue("operation") + + second, err := strconv.Atoi(req.FormValue("second")) + if err != nil { + log.Fatal("cannot parse second", err) + } + + var guess int + answer := req.FormValue("answer") + if answer == "" { + guess = 0 + } else { + guess, err = strconv.Atoi(answer) + if err != nil { + log.Fatal("cannot parser answer", err) + } + } + + var result bool + if operation == "+" { + result = first+second == guess + } else if operation == "-" { + result = first-second == guess + } + + session, _ := store.Get(req, "Score") + score := getScore(session) + if result { + score += 1 + } else { + score -= 1 + } + session.Values["Score"] = score + session.Save(req, w) + + b, err := json.Marshal(solution{result, score}) + if err != nil { + log.Fatal("cannot marshal solution", err) + } + j := string(b) + fmt.Println("attempt", j) + fmt.Fprintf(w, j) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..6ee659d --- /dev/null +++ b/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "flag" + "github.com/gorilla/sessions" + "log" + "math/rand" + "net/http" + "os" + "time" +) + +const MAX = 12 + +var addr = flag.String("addr", ":8000", "address I'll listen on.") +var static_files = flag.String("static", "./static", "location of static files") + +var store = sessions.NewCookieStore([]byte(os.Getenv("MMG_SECRET_KEY"))) + +func main() { + rand.Seed(time.Now().UTC().UnixNano()) + flag.Parse() + http.Handle("/", + http.FileServer(http.Dir(*static_files))) + http.Handle("/api/v0/problem/", JsonHandler(problem)) + http.Handle("/api/v0/attempt/", JsonHandler(attempt)) + if err := http.ListenAndServe(*addr, nil); err != nil { + log.Fatal("ListenAndServe:", err) + } +} diff --git a/manage.py b/manage.py deleted file mode 100644 index 256b565..0000000 --- a/manage.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mmg.settings") - - from django.core.management import execute_from_command_line - - execute_from_command_line(sys.argv) diff --git a/mmg/__init__.py b/mmg/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mmg/settings.py b/mmg/settings.py deleted file mode 100644 index ca0b45a..0000000 --- a/mmg/settings.py +++ /dev/null @@ -1,88 +0,0 @@ -import os - -DEBUG = False -TEMPLATE_DEBUG = DEBUG - -ADMINS = ( - ('Stephen McQuay', 'stephen@mcquay.me'), -) -MANAGERS = ADMINS -ALLOWED_HOSTS = ['mmg.mcquay.me', 'midna.local'] - -TIME_ZONE = 'America/Chicago' - -LANGUAGE_CODE = 'en-us' -SITE_ID = 1 -USE_I18N = True -USE_L10N = True -USE_TZ = True -MEDIA_ROOT = '' -MEDIA_URL = '' - -STATIC_ROOT = os.path.expanduser('~/tmp/mmg') -STATIC_URL = 'http://tmp.mcquay.me/mmg/' -STATICFILES_DIRS = ( - os.path.expanduser('~/src/mmg/static'), -) - -STATICFILES_FINDERS = ( - 'django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', -) - -SECRET_KEY = os.environ.get('MMG_SECRET_KEY') - -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', -) - -MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', -) - -ROOT_URLCONF = 'mmg.urls' - -WSGI_APPLICATION = 'mmg.wsgi.application' - -TEMPLATE_DIRS = ( - os.path.expanduser('~/src/mmg/templates'), -) - -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', -) - -SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' - -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'filters': { - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse' - } - }, - 'handlers': { - 'mail_admins': { - 'level': 'ERROR', - 'filters': ['require_debug_false'], - 'class': 'django.utils.log.AdminEmailHandler' - } - }, - 'loggers': { - 'django.request': { - 'handlers': ['mail_admins'], - 'level': 'ERROR', - 'propagate': True, - }, - } -} diff --git a/mmg/urls.py b/mmg/urls.py deleted file mode 100644 index 535f3ca..0000000 --- a/mmg/urls.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.conf.urls import patterns, url - -urlpatterns = patterns( - '', - url(r'^$', 'mmg.views.home', name='home'), - url(r'^api/v0/attempt/$', 'mmg.views.attempt', name='attempt'), - url(r'^api/v0/problem/$', 'mmg.views.problem', name='problem'), -) diff --git a/mmg/views.py b/mmg/views.py deleted file mode 100644 index 60ababf..0000000 --- a/mmg/views.py +++ /dev/null @@ -1,63 +0,0 @@ -import json -import random - -from django.http import HttpResponse -from django.shortcuts import render - -MAX = 12 - - -def _generate_problem(): - operation = random.choice(['+', '-']) - first = random.choice(range(MAX)) - if operation == '-': - if first == 0: - second = 0 - else: - second = random.choice(range(first)) - else: - second = random.choice(range(MAX)) - return { - 'first': first, - 'operation': operation, - 'second': second, - } - - -def _validate_solution(a): - f = int(a['first']) - o = a['operation'] - s = int(a['second']) - if a['answer'] == '': - g = 0 - else: - g = int(a['answer']) - r = False - if o == '+': - r = bool(f + s == g) - else: - r = bool(f - s == g) - return r - - -def home(request): - return render(request, 'index.html') - - -def attempt(request): - d = request.POST.dict() - r = _validate_solution(d) - if r: - s = request.session.get('score', 0) + 1 - else: - s = request.session.get('score', 0) - 1 - request.session['score'] = s - return HttpResponse( - json.dumps({'status': r, 'score': s}), - content_type="application/json") - - -def problem(request): - d = _generate_problem() - d['score'] = request.session.get('score', 0) - return HttpResponse(json.dumps(d), content_type="application/json") diff --git a/mmg/wsgi.py b/mmg/wsgi.py deleted file mode 100644 index 12ad688..0000000 --- a/mmg/wsgi.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -WSGI config for mmg project. - -This module contains the WSGI application used by Django's development server -and any production WSGI deployments. It should expose a module-level variable -named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover -this application via the ``WSGI_APPLICATION`` setting. - -Usually you will have the standard Django WSGI application here, but it also -might make sense to replace the whole Django WSGI application with a custom one -that later delegates to the Django one. For example, you could introduce WSGI -middleware here, or combine a Django application with an application of another -framework. - -""" -import os - -# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks -# if running multiple sites in the same mod_wsgi process. To fix this, use -# mod_wsgi daemon mode with each site in its own daemon process, or use -# os.environ["DJANGO_SETTINGS_MODULE"] = "mmg.settings" -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mmg.settings") - -# This application object is used by any WSGI server configured to use this -# file. This includes Django's development server, if the WSGI_APPLICATION -# setting points here. -from django.core.wsgi import get_wsgi_application -application = get_wsgi_application() - -# Apply WSGI middleware here. -# from helloworld.wsgi import HelloWorldApplication -# application = HelloWorldApplication(application) diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 17311a1..0000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -Django==1.5.1 -gunicorn==0.17.2 diff --git a/templates/index.html b/static/index.html similarity index 69% rename from templates/index.html rename to static/index.html index 5f8ac89..09c0ff9 100644 --- a/templates/index.html +++ b/static/index.html @@ -1,10 +1,9 @@ -{% load staticfiles %} - {{ title }} + Mardson's Math Game - +
@@ -18,7 +17,7 @@ - - + + diff --git a/static/math.js b/static/math.js index 1cfb180..f49a1c1 100644 --- a/static/math.js +++ b/static/math.js @@ -7,7 +7,7 @@ function update_board(f, o, s, score) { function new_problem() { $.get("/api/v0/problem/", function(d) { - update_board(d["first"], d["operation"], d["second"], d["score"]); + update_board(d["First"], d["Operation"], d["Second"], d["Score"]); $("#answer").val(""); }) } @@ -20,7 +20,8 @@ function deal_with_answer(e) { "answer": $("#answer").val(), }; $.post("/api/v0/attempt/", data, function(d) { - if(d["status"]) { + $("#score").text(d["Score"]); + if(d["Status"]) { $("body").removeClass("wrong"); new_problem(); } @@ -35,7 +36,7 @@ function deal_with_answer(e) { $(function() { new_problem(); $("#answer").keypress(function(e) { - if( e.which == 13) { + if (e.which == 13 || e.which == 32) { deal_with_answer(e); } });