Advertisement
Guest User

Untitled

a guest
Oct 7th, 2012
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.48 KB | None | 0 0
  1. from google.appengine.ext import webapp
  2. import random
  3. import pickle
  4. from operator import mul
  5. import operator
  6. import HTML
  7. from google.appengine.ext import ndb
  8. from google.appengine.api import memcache
  9. import csv
  10. from google.appengine.ext import deferred
  11. MEMCACHE_MAX_ITEM_SIZE = 900 * 1024
  12.  
  13. TOSS = 500
  14. PLAYERS = 100
  15.  
  16. class simple_counter(ndb.Model):
  17.     counter = ndb.IntegerProperty(default=0)
  18.  
  19.  
  20.  
  21. class score_history(ndb.Model):
  22.     chart_data = ndb.TextProperty()
  23.     dt = ndb.DateTimeProperty(auto_now=True)
  24.  
  25. class highest_score(ndb.Model):
  26.     score = ndb.TextProperty()
  27.     @classmethod
  28.     def return_current_highest(cls):
  29.         s = memcache.get('largest_ever')
  30.         if s is None:
  31.             x = highest_score.get_or_insert('current_highest')
  32.             score = x.score
  33.             if score is None:
  34.                 memcache.set('largest_ever',0)
  35.                 return 0
  36.             else:
  37.                 memcache.set('largest_ever',int(score))
  38.                 return int(score)
  39.         else:
  40.             return s
  41.  
  42.     @classmethod
  43.     def set_new_highest_score(cls,score):
  44.         x = highest_score.get_or_insert('current_highest') # todo hmm.
  45.         saved_highest = x.score
  46.         if saved_highest is None:
  47.                 x.score = str(score)
  48.                 x.put()
  49.                 memcache.set('largest_ever',int(score))
  50.                 saved_highest = x.score
  51.         if int(saved_highest)<score:
  52.                 x.score = str(score)
  53.                 x.put()
  54.                 c = score_history()
  55.                 c.chart_data= str(score)
  56.                 c.put()
  57.                 memcache.set('largest_ever',int(score))
  58.  
  59.  
  60. class current_round_data(ndb.Model):
  61.     data = ndb.PickleProperty()
  62.  
  63.  
  64. # todo track two strings side by side marking changes as you go, as tool.
  65.  
  66. def create_new_generation():
  67.     memcache_data = memcache.get('saved_round_data')
  68.     if memcache_data is None:
  69.         saved_data = current_round_data.get_or_insert('saved_round_data')
  70.     else:
  71.         saved_data = memcache_data
  72.     sorted_candidate_list = make_ten_generations(saved_data.data)
  73.     sorted_candidate_list = sorted(sorted_candidate_list,key=operator.itemgetter(1)) # sort by the score in the tuple
  74.     sorted_candidate_list.reverse() # reverse it so that the highest score is first
  75.  
  76.     winner = sorted_candidate_list[0][1] # The person with the highest product wins. [0] is the first item in the list, and [1] is the second item in that item, i.e. the score
  77.     highest_score.set_new_highest_score(winner)
  78.  
  79.     saved_data.data=sorted_candidate_list
  80.     d= saved_data.data
  81.     saved_data.put()
  82.     memcache.set('saved_round_data',saved_data)
  83.  
  84.  
  85.  
  86. class generations(webapp.RequestHandler):
  87.     def get(self):
  88.  
  89.         memcache_data = memcache.get('saved_round_data')
  90.         if memcache_data is None:
  91.             saved_data = current_round_data.get_or_insert('saved_round_data')
  92.             if saved_data.data is None:
  93.                 create_new_generation()
  94.                 self.redirect('/')
  95.                 return
  96.         else:
  97.             saved_data = memcache_data.data
  98.  
  99.         render_details(self,saved_data)
  100.  
  101. def make_ten_generations(saved_data=None):
  102.     sc = simple_counter.get_or_insert('just_the_one')
  103.     sc.counter+=1 # update the counters only when we make a new generation
  104.     sc.put()
  105.  
  106.     if saved_data is None:
  107.         data = play_a_round() # generate a list ['H','H','T',...]
  108.     else:
  109.         n = []
  110.         for d, score in saved_data:
  111.             n.append(d)
  112.         data = n # use what we're passed
  113.         #todo this sucks
  114.     candidate_list = determine_score(data) #score the data by creating a tuple with the data in postion 0 and the score in position 1
  115.  
  116.     i = 0
  117.     while i<1:
  118.         candidate_list=new_generation(candidate_list)
  119.         i+=1
  120.  
  121.     return candidate_list
  122.  
  123. class MainHandler(webapp.RequestHandler):
  124.     def get(self):
  125.  
  126.         create_new_generation()
  127.  
  128. def render_details(self,sorted_candidate_list):
  129.  
  130.         sc = simple_counter.get_or_insert('just_the_one')
  131.  
  132.         memd = get('prerendered_data'+str(sc.counter))
  133.  
  134.         if memd:
  135.             self.response.out.write(memd)
  136.             return
  137.  
  138.         winner = sorted_candidate_list[0][1] # The person with the highest product wins. [0] is the first item in the list, and [1] is the second item in that item, i.e. the score
  139.  
  140.  
  141.         s = []
  142.         if winner > 10**60:
  143.             s.append("we have a winner with a score of {0}".format(winner))
  144.         else:
  145.             s.append('A new generation will be created every 1 minute.  Mutation rate is in 1 in 10 that a particular toss value will change to a randomly selected value that might be the same as the value it is replacing.<br>'
  146.                                     'This is iteration {3}<br> Refresh the page in a minute to see the next generation.'
  147.                                     'Highest score this round {0}<br>'
  148.                                     'Which is<br>{1}<br>away from the target of <br>'
  149.                                     '{2}'
  150.                                     ''
  151.                                     ''.format(winner,10**60-winner,10**60,sc.counter))
  152.  
  153.         s.append('<br>Largest score generated so far: {0}'.format(highest_score.return_current_highest()))
  154.  
  155.         table = render_table(sorted_candidate_list)
  156.         ss = ''.join(s)
  157.         sss = ss + table
  158.         set('prerendered_data'+str(sc.counter),sss)
  159.         self.response.out.write(sss)
  160.  
  161. #todo graph score over time.
  162.  
  163. def render_table(current_round_list_of_tuples):
  164.  
  165.     t = HTML.Table(header_row=['Score'])
  166.     try:
  167.         for i, (data, score) in enumerate(current_round_list_of_tuples):
  168.             colored_data = []
  169.             for toss in data:
  170.  
  171.                 if toss =='H':
  172.                     colored_data.append(HTML.TableCell('H', bgcolor='green'))
  173.                 else:
  174.                     colored_data.append(HTML.TableCell('T', bgcolor='grey'))
  175.  
  176.             x = [score]
  177.             x.extend(colored_data)
  178.             t.rows.append(x)
  179.     except ValueError:
  180.         pass
  181.     htmlcode = str(t)
  182.     return htmlcode
  183.  
  184. def split_list(alist, wanted_parts=1):
  185.     length = len(alist)
  186.     return [alist[i * length // wanted_parts: (i + 1) * length // wanted_parts]
  187.             for i in range(wanted_parts)]
  188.  
  189. def determine_score(list_list_of_tosses):
  190.     round_score = []
  191.     for r in list_list_of_tosses:
  192.         counter = 0
  193.         score = []
  194.         for toss in r:
  195.             if toss == 'H':
  196.                 # As they do so, they record all runs of heads
  197.                 counter+=1
  198.             if toss == 'T':
  199.                 # so that if they toss H T T H H H T H T T H H H H T T T,
  200.                 if counter > 0:
  201.                     #   they will record: 1, 3, 1, 4, representing the number of heads in each run.
  202.                     score.append(counter)
  203.                 counter = 0
  204.         round_score.append(score)
  205.  
  206.     final_scores = []
  207.     for i, player_scores in enumerate(round_score):
  208.         # At the end of each round, each player computes the product of their runs-of-heads.
  209.         final_scores.append((list_list_of_tosses[i],reduce(mul,player_scores))) # keep the scores and the list together via a tuple
  210.  
  211.  
  212.     return final_scores
  213.  
  214. def point_mutate(a_list):
  215.     new_list = a_list[:]
  216.     for i, toss in enumerate(a_list):
  217.         counter = random.randint(0,100)
  218.         if counter > 90:
  219.             new_list[i] = (random.choice(['H','T'])) # generate a new value
  220.  
  221.     return new_list
  222.  
  223. def play_a_round():
  224.     round = []
  225.     for t in range(PLAYERS):
  226.     # On each turn, players toss a fair coin 500 times.
  227.         player_round = []
  228.         for p in range(TOSS):
  229.             player_round.append(random.choice(['H','T']))
  230.         round.append(player_round)
  231.     return round
  232.  
  233.  
  234. def new_generation(sorted_candidate_list):
  235.  
  236.     l = len(sorted_candidate_list)
  237.     half = l/2
  238.     sorted_candidate_list = sorted(sorted_candidate_list,key=operator.itemgetter(1)) # sort by the score in the tuple
  239.  
  240.     sorted_candidate_list.reverse()
  241.     without_bottom_50 = sorted_candidate_list[:half]
  242.  
  243.     new_50_items = []
  244.  
  245.     try:
  246.         for existing_item, score in without_bottom_50:
  247.             new_string = point_mutate(existing_item)
  248.             new_50_items.append(new_string)
  249.     except ValueError:
  250.         pass
  251.  
  252.     data_only = []
  253.     for data, score in without_bottom_50: # get rid of the tuple score now.
  254.         data_only.append(data)
  255.  
  256.     data_only.extend(new_50_items)
  257.     new_scored_list = determine_score(data_only)
  258.     return new_scored_list
  259.  
  260.  
  261. def delete(key):
  262.     chunk_keys = memcache.get(key)
  263.     if chunk_keys is None:
  264.         return False
  265.     chunk_keys.append(key)
  266.     memcache.delete_multi(chunk_keys)
  267.     return True
  268.  
  269.  
  270. def set(key, value):
  271.     pickled_value = pickle.dumps(value)
  272.  
  273.     # delete previous entity with the given key
  274.     # in order to conserve available memcache space.
  275.     delete(key)
  276.  
  277.     pickled_value_size = len(pickled_value)
  278.     chunk_keys = []
  279.     for pos in range(0, pickled_value_size, MEMCACHE_MAX_ITEM_SIZE):
  280.         # TODO: use memcache.set_multi() for speedup, but don't forget
  281.         # about batch operation size limit (32Mb currently).
  282.         chunk = pickled_value[pos:pos + MEMCACHE_MAX_ITEM_SIZE]
  283.  
  284.         # the pos is used for reliable distinction between chunk keys.
  285.         # the random suffix is used as a counter-measure for distinction
  286.         # between different values, which can be simultaneously written
  287.         # under the same key.
  288.         chunk_key = '%s%d%d' % (key, pos, random.getrandbits(31))
  289.  
  290.         is_success = memcache.set(chunk_key, chunk)
  291.         if not is_success:
  292.             return False
  293.         chunk_keys.append(chunk_key)
  294.     return memcache.set(key, chunk_keys)
  295.  
  296.  
  297. def get(key):
  298.     chunk_keys = memcache.get(key)
  299.     if chunk_keys is None:
  300.         return None
  301.     chunks = []
  302.     for chunk_key in chunk_keys:
  303.         # TODO: use memcache.get_multi() for speedup.
  304.         # Don't forget about the batch operation size limit (currently 32Mb).
  305.         chunk = memcache.get(chunk_key)
  306.         if chunk is None:
  307.             return None
  308.         chunks.append(chunk)
  309.     pickled_value = ''.join(chunks)
  310.     try:
  311.         return pickle.loads(pickled_value)
  312.     except Exception:
  313.         return None
  314.  
  315.  
  316.  
  317.  
  318.  
  319. app = webapp.WSGIApplication([
  320.                                   ('/random', MainHandler) ,
  321.                                     ('/', generations)
  322. ],
  323.                              debug=True)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement