Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: saurya/minigiant
base: 4abbb695eb
...
head fork: saurya/minigiant
compare: 698ad952bf
  • 1 commit
  • 14 files changed
  • 0 commit comments
  • 1 contributor
Commits on Oct 19, 2012
Saurya Velagapudi Trimming shit down 698ad95
57 addfriend.py
View
@@ -0,0 +1,57 @@
+import os
+import cgi
+import common
+import datetime
+import re
+import models
+import webapp2
+
+from google.appengine.ext import db
+from google.appengine.api import mail
+from google.appengine.api import users
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+
+FRIEND_NICK_PARAM = "f"
+USER_ID_PARAM = "u"
+ADD_FN = "addFriend"
+
+class AddFriendHandler(webapp2.RequestHandler):
+ def emailFriend(self, friend):
+ mail.send_mail(sender="saurya@gmail.com",
+ to=friend.nickname() + " <" + friend.email() + ">",
+ subject="A friend wants to challenge you to workout!",
+ body="""
+ Hey there!
+
+ Head on over to http://omarvssaurya.appspot.com and track your workouts!
+ One of your friends, who has already been using it, wants to challenge you.
+
+ The way it works: you can track your own workouts. Add friends, to see how
+ they're doing and compete with them!
+
+ Cheers,
+ The Workout Challenge Team
+ """)
+
+ def get(self):
+ user_id = self.request.get(USER_ID_PARAM)
+ parent_key = db.Key.from_path("User", user_id)
+ contest = models.Contest().all().ancestor(parent_key).get()
+ friend = users.User(self.request.get(FRIEND_NICK_PARAM))
+ if contest and friend not in contest.participants:
+ contest.participants.append(friend)
+ contest.put()
+ friend_contest = models.Contest().all().filter('user =', friend).get()
+ if not friend_contest:
+ self.emailFriend(friend)
+ else:
+ friend = friend_contest.user
+ # Render JSONP Response
+ path = os.path.join(os.path.dirname(__file__), 'scorecard.html')
+ self.response.headers['Content-Type'] = 'applicaton/javascript'
+ self.response.out.write(ADD_FN + "('" + common.renderDays(friend, path) + "')")
+
+app = webapp2.WSGIApplication([
+ ('/addfriend', AddFriendHandler)
+], debug=True)
25 app.yaml
View
@@ -0,0 +1,25 @@
+application: omarvssaurya
+version: 1
+runtime: python27
+api_version: 1
+threadsafe: yes
+handlers:
+- url: /favicon\.ico
+ static_files: favicon.ico
+ upload: favicon\.ico
+
+- url: /log
+ script: log.app
+- url: /delete
+ script: delete.app
+- url: /addfriend
+ script: addfriend.app
+- url: /deletefriend
+ script: deletefriend.app
+- url: .*
+ script: main.app
+
+
+libraries:
+- name: webapp2
+ version: "2.5.1"
53 common.py
View
@@ -0,0 +1,53 @@
+import models
+import os
+import datetime
+from google.appengine.ext import db
+from google.appengine.ext.webapp import template
+
+class Record(list):
+ pass
+
+# returns a tuple of (score, entries_by_date)
+def getDays(user):
+ your_score = 0
+ index = -1
+ date = []
+ yourdays = Record()
+ # run the query to get all entries for this user
+ parent_key = db.Key.from_path("User", user.user_id())
+ entries = models.Entry().all()
+ entries.ancestor(parent_key)
+ entries.order('-date')
+ your_entries = entries.run()
+ for entry in your_entries:
+ if date != entry.date.date():
+ date = entry.date.date()
+ day = Record()
+ day.date = date
+ yourdays.append(day)
+ index += 1
+ your_score += entry.points
+ yourdays[index].append(entry)
+ yourdays.name = user.nickname().split("@")[0]
+ yourdays.score = your_score
+ yourdays.nickname = user.nickname()
+ return yourdays
+
+def renderDays(user, path):
+ yourdays = getDays(user)
+ today = Record()
+ today.date = datetime.datetime.now().date()
+ if len(yourdays) == 0 or yourdays[0].date != today.date:
+ yourdays.insert(0, today)
+ template_values = {
+ 'yourdays' : yourdays
+ }
+ return template.render(path, template_values)
+
+def getCompetitors(user):
+ contest = models.Contest.all()
+ contest.filter('user =', user)
+ user_contest = contest.get()
+ if user_contest:
+ return user_contest.participants
+ return []
26 delete.py
View
@@ -0,0 +1,26 @@
+import os
+import cgi
+import datetime
+import re
+import models
+import webapp2
+
+from google.appengine.ext import db
+from google.appengine.api import users
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+
+ENTRY_ID_PARAM = "e"
+USER_ID_PARAM = "u"
+
+class DeleteHandler(webapp2.RequestHandler):
+ def get(self):
+ user_id = self.request.get(USER_ID_PARAM)
+ key = self.request.get(ENTRY_ID_PARAM)
+ entry = models.Entry(key=key)
+ db.delete(entry)
+
+
+app = webapp2.WSGIApplication([
+ ('/delete', DeleteHandler)
+], debug=True)
28 deletefriend.py
View
@@ -0,0 +1,28 @@
+import os
+import cgi
+import datetime
+import re
+import models
+import webapp2
+
+from google.appengine.ext import db
+from google.appengine.api import users
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+
+FRIEND_NICK_PARAM = "f"
+USER_ID_PARAM = "u"
+
+class DeleteFriendHandler(webapp2.RequestHandler):
+ def get(self):
+ user_id = self.request.get(USER_ID_PARAM)
+ parent_key = db.Key.from_path("User", user_id)
+ contest = models.Contest().all().ancestor(parent_key).get()
+ friend = users.User(self.request.get(FRIEND_NICK_PARAM))
+ if contest and friend in contest.participants:
+ contest.participants.remove(friend)
+ contest.put()
+
+app = webapp2.WSGIApplication([
+ ('/deletefriend', DeleteFriendHandler)
+], debug=True)
BIN  favicon.ico
View
Binary file not shown
17 index.yaml
View
@@ -0,0 +1,17 @@
+indexes:
+
+# AUTOGENERATED
+
+# This index.yaml is automatically updated whenever the dev_appserver
+# detects that a new type of query is run. If you want to manage the
+# index.yaml file manually, remove the above marker line (the line
+# saying "# AUTOGENERATED"). If you want to manage some indexes
+# manually, move them above the marker line. The index.yaml file is
+# automatically uploaded to the admin console when you next deploy
+# your application using appcfg.py.
+
+- kind: Entry
+ ancestor: yes
+ properties:
+ - name: date
+ direction: desc
51 log.py
View
@@ -0,0 +1,51 @@
+import os
+import cgi
+import datetime
+import re
+import models
+import webapp2
+
+from google.appengine.ext import db
+from google.appengine.api import users
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+
+QUERY_CGI_PARAM = "q"
+USER_ID_PARAM = "u"
+ADD_FN = "addNewEntry"
+
+class LogHandler(webapp2.RequestHandler):
+ def getExerciseName(self, query):
+ words = [s for s in query.split() if not s.isdigit()]
+ return words[0]
+
+ def getExercise(self, query):
+ return models.exercises[self.getExerciseName(query)]
+
+ def getNumber(self, query):
+ numbers = [int(s) for s in query.split() if s.isdigit()]
+ return numbers[0]
+
+ def get(self):
+ user_id = self.request.get(USER_ID_PARAM)
+ parent_key = db.Key.from_path("User", user_id)
+ contest = models.Contest.all().ancestor(parent_key).get()
+ nickname = contest.user.nickname()
+ entry = models.Entry(parent=parent_key)
+ query = self.request.get(QUERY_CGI_PARAM)
+ exercise = self.getExercise(query)
+ entry.date = datetime.datetime.now()
+ entry.reps = self.getNumber(query)
+ entry.points = exercise[2] * entry.reps
+ entry.name = exercise[0]
+ entry.put()
+
+ if user_id:
+ # Render JSONP Response
+ self.response.headers['Content-Type'] = 'applicaton/javascript'
+ self.response.out.write(ADD_FN + '(' + str(entry.points) + ',"' + entry.name + '", "' + nickname + '", "' + str(entry.key()) + '")')
+
+
+app = webapp2.WSGIApplication([
+ ('/log', LogHandler)
+], debug=True)
228 log_workout.html
View
@@ -0,0 +1,228 @@
+<html>
+<style>
+.scoreboard {
+ display: inline-block;
+ width:40%;
+ height: 40%;
+ overflow-y:auto;
+ overflow-x:hidden;
+ border: 1px solid black;
+ margin: 2px;
+ border-radius: 3px 3px 3px 1px;
+ background: rgba(242, 242, 242, 0.8);
+ position: relative;
+}
+#you {
+ border: 3px solid black;
+ box-shadow: #888 5px 5px 5px;
+}
+.entry {
+ border: 1px solid rgb(100, 100, 242);
+ padding: 6px;
+ min-height: 20px;
+}
+.exercise {
+ display: inline-block;
+ max-width: 30%;
+ font-family: sans-serif;
+}
+.points {
+ display: inline-block;
+ max-width: 30%;
+ left: 40%;
+ position: absolute;
+ font-style: italic;
+ font-weight: bold;
+}
+.score {
+ font-size: 50px;
+ position: absolute;
+ padding: 2px;
+ background: rgba(200, 242, 242, 0.9);
+ right: 0px;
+ z-index: 99;
+ bottom: 0px;
+ border-radius: 5px 0px 0px 0px;
+ cursor: default;
+}
+.name {
+ position: absolute;
+ right: 0px;
+ top: 0px;
+ background: rgba(200, 242, 242, 0.9);
+ border-radius: 0px 3px 0px 0px;
+ padding: 4px;
+ font-size:30px;
+ cursor: default;
+}
+.entry:hover {
+ opacity: 0.3;
+ cursor: pointer;
+}
+.date_separator {
+ border: 1px solid black;
+ height: 3px;
+}
+.date {
+ border: 1px solid black;
+ padding: 3px;
+}
+.delete_friend:hover {
+ background: rgb(250, 50, 50);
+}
+.default_translucent {
+ opacity: 0.6;
+}
+input {
+ margin: 10px;
+ min-width: 10%;
+ max-width: 20%;
+}
+</style>
+
+<!--Slider-->
+
+
+<input type="text" id="tf" class="cleardefault default_translucent" default_value="Enter workout" value="Enter workout"></input>
+<input type="text" id="ff" class="cleardefault default_translucent" default_value="Enter friend's e-mail" value="Enter friend's e-mail"></input>
+<div id="scorecards">
+
+{% for yourdays in users %}
+<div {% if forloop.first %}id="you"{% endif %} class="scoreboard" nickname="{{yourdays.nickname}}">
+ {% for day in yourdays %}
+ <div class="date">{{day.date}}</div>
+ <div class="day">
+ {% for exercise in day %}
+ <div class="entry" {% if forloop.parentloop.first %}entry_id="{{exercise.key}}"{% endif %}>
+ <div class="exercise">
+ {{exercise.name}}
+ </div>
+ <div class="points">
+ +{{exercise.points}}
+ </div>
+ </div>
+ {% endfor %}
+ </div>
+ <div class="date_separator"></div>
+ {% endfor %}
+ <div class="score">{{yourdays.score}}</div>
+ <div class="name {% if not forloop.first %}delete_friend{% endif %}">
+ {{yourdays.name}}
+ </div>
+</div>
+{% endfor %}
+
+</div>
+
+<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"> </script>
+<script>
+String.prototype.format = function() {
+ var args = arguments;
+ return this.replace(/{(\d+)}/g, function(match, number) {
+ return typeof args[number] != 'undefined'
+ ? args[number]
+ : match
+ ;
+ });
+};
+var entryHtml = '<div class="entry" entry_id="{2}"> \
+ <div class="exercise"> \
+ {0} \
+ </div> \
+ <div class="points"> \
+ +{1} \
+ </div> \
+ </div>'
+
+var score = {{score}};
+var user_id = "{{user_id}}";
+var parser = new DOMParser();
+var Ids = {
+ SCORE_CARDS : "scorecards",
+ JSONP_REQUEST : "jsonp",
+ TEXT_FIELD : "tf",
+ FRIEND_FIELD: "ff",
+ YOUR_SCORECARD: "you"
+};
+var Classes = {
+ DAYS: "day",
+ ENTRY: "entry",
+ SCORE_CARD: "scoreboard",
+ DELETE_FRIEND: "delete_friend",
+ CLEAR_DEFAULT: "cleardefault",
+ DEFAULT_TRANSLUCENT: "default_translucent"
+};
+$('#' + Ids.TEXT_FIELD).keypress(function(e) {
+ if (e.which == 13) {
+ updateBackend();
+ }
+});
+$('#' + Ids.FRIEND_FIELD).keypress(function(e) {
+ if (e.which == 13) {
+ updateFriends();
+ }
+});
+function makeJsonpRequest(url) {
+ var $script = $('<script>');
+ $script.attr('src', url);
+ $('body').append($script);
+}
+function deleteFromBackend() {
+ var entry_id = $(this).attr('entry_id');
+ makeJsonpRequest('/delete?u=' + user_id + '&e=' + entry_id);
+ var points = $(this).children('.points').html();
+ score -= parseInt(points, 10);
+ var scorecard = $('#' + Ids.YOUR_SCORECARD);
+ scorecard.find('.score').text(score);
+ $(this).remove();
+}
+function deleteFriendFromBackend() {
+ var scorecard = $(this).parents('.' + Classes.SCORE_CARD);
+ var friend_name = scorecard.attr('nickname');
+ makeJsonpRequest('/deletefriend?u=' + user_id + '&f=' + friend_name);
+ scorecard.hide('slow');
+ scorecard.remove();
+}
+function updateFriends() {
+ var text_field = $('#' + Ids.FRIEND_FIELD);
+ var url = '/addfriend?u=' + user_id + '&f=' + text_field.val();
+ text_field.val("");
+ makeJsonpRequest(url);
+}
+function updateBackend() {
+ var text_field = $('#' + Ids.TEXT_FIELD);
+ var url = '/log?u=' + user_id + '&q=' + text_field.val().replace(' ', '+');
+ text_field.val("");
+ makeJsonpRequest(url);
+}
+function addNewEntry(points, name, nickname, entry_id) {
+ var exercise = $('<div>').html(entryHtml.format(name, points, entry_id));
+ score += points;
+ var scorecard = $('[nickname="' + nickname + '"]');
+ var logbook = scorecard.find('.' + Classes.DAYS + ":first");
+ logbook.prepend(exercise);
+ exercise.find('.' + Classes.ENTRY).click(deleteFromBackend);
+ scorecard.find('.score').text(score);
+}
+function addFriend(htmlString) {
+ var scorecard = $(htmlString);
+ $('#' + Ids.SCORE_CARDS).append(scorecard);
+}
+function clearDefault() {
+ var defaultValue = $(this).attr('default_value');
+ if ($(this).val() == defaultValue) {
+ $(this).val("");
+ }
+ $(this).removeClass(Classes.DEFAULT_TRANSLUCENT);
+ $(this).focusout(makeDefault);
+}
+function makeDefault() {
+ var defaultValue = $(this).attr('default_value');
+ $(this).val(defaultValue);
+ $(this).addClass(Classes.DEFAULT_TRANSLUCENT);
+}
+$('#' + Ids.YOUR_SCORECARD).find('.' + Classes.ENTRY).click(deleteFromBackend);
+$('.' + Classes.DELETE_FRIEND).click(deleteFriendFromBackend);
+$('.' + Classes.CLEAR_DEFAULT).focus(clearDefault);
+</script>
+</html>
0  main.app
View
No changes.
60 main.py
View
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import webapp2
+
+import os
+import datetime
+import models
+import common
+from google.appengine.ext import db
+from google.appengine.api import users
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+
+class MainHandler(webapp2.RequestHandler):
+ def get(self):
+ current_user = users.get_current_user()
+ if not current_user:
+ self.redirect(users.create_login_url(self.request.uri))
+ return
+ contest = models.Contest.all().filter('user =', current_user).get()
+ if not contest:
+ contest = models.Contest(parent=db.Key.from_path("User", current_user.user_id()),user=current_user)
+ contest.put()
+ competitors = common.getCompetitors(current_user)
+ everyone = [common.getDays(competitor) for competitor in competitors]
+ user_entries = common.getDays(current_user)
+ today = common.Record()
+ today.date = datetime.datetime.now().date()
+ if len(user_entries) == 0 or user_entries[0].date != today.date:
+ user_entries.insert(0, today)
+
+ everyone.insert(0, user_entries)
+ # Fetch records for others
+ # Fetch my record
+ template_values = {
+ 'users' : everyone,
+ 'score' : user_entries.score,
+ 'user_id' : current_user.user_id(),
+ }
+ path = os.path.join(os.path.dirname(__file__), 'log_workout.html')
+ self.response.out.write(template.render(path, template_values))
+
+
+app = webapp2.WSGIApplication([
+ ('/', MainHandler)
+], debug=True)
21 models.py
View
@@ -0,0 +1,21 @@
+from google.appengine.ext import db
+from google.appengine.api import users
+
+exercises = { 'pushups' : ('pushups', 'reps', 10),
+ 'pullups' : ('pullups', 'reps', 10),
+ 'burpees' : ('burpees', 'reps', 20),
+ 'squats' : ('squats', 'reps', 10),
+ 'punching' : ('punching', 'minutes', 60),
+ 'jumping' : ('jumping', 'minutes', 40),
+ 'plank' : ('plank', 'minutes', 60) }
+
+class Entry(db.Model):
+ reps = db.IntegerProperty()
+ points = db.IntegerProperty()
+ date = db.DateTimeProperty()
+ name = db.StringProperty(choices=set(exercises.keys()))
+
+class Contest(db.Model):
+ participants = db.ListProperty(users.User)
+ user = db.UserProperty()
+
31 newcontest.py
View
@@ -0,0 +1,31 @@
+import os
+import cgi
+import datetime
+import re
+import models
+import webapp2
+
+from google.appengine.ext import db
+from google.appengine.api import users
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+
+REPS_CGI_PARAM = "r"
+
+class MainHandler(webapp2.RequestHandler):
+ def get(self):
+ entry = models.Entry
+ # entry.time = get the current time
+ entry.reps = self.request.get(REPS_CGI_PARAM)
+ entry.user = users.get_current_user()
+ entry.points = exercise.points_per_unit * entry.reps
+
+ if entry.user:
+ # Render JSONP Response
+ self.response.headers['Content-Type'] = 'applicaton/javascript'
+ self.response.out.write(ADD_FN + '(' + entry.points + ',' + entry.exercise.name)
+
+
+app = webapp2.WSGIApplication([
+ ('/', MainHandler)
+], debug=True)
22 scorecard.html
View
@@ -0,0 +1,22 @@
+<div class="scoreboard" nickname="{{yourdays.nickname}}"> \
+ {% for day in yourdays %} \
+ <div class="date">{{day.date}}</div> \
+ <div class="day"> \
+ {% for exercise in day %} \
+ <div class="entry"> \
+ <div class="exercise"> \
+ {{exercise.name}} \
+ </div> \
+ <div class="points"> \
+ +{{exercise.points}} \
+ </div> \
+ </div> \
+ {% endfor %} \
+ </div> \
+ <div class="date_separator"></div> \
+ {% endfor %} \
+ <div class="score">{{yourdays.score}}</div> \
+ <div class="name delete_friend"> \
+ {{yourdays.name}} \
+ </div> \
+</div>

No commit comments for this range

Something went wrong with that request. Please try again.