Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from google.appengine.ext import webapp
- import random
- import pickle
- from operator import mul
- import operator
- import HTML
- from google.appengine.ext import ndb
- from google.appengine.api import memcache
- import csv
- from google.appengine.ext import deferred
- MEMCACHE_MAX_ITEM_SIZE = 900 * 1024
- TOSS = 500
- PLAYERS = 100
- class simple_counter(ndb.Model):
- counter = ndb.IntegerProperty(default=0)
- class score_history(ndb.Model):
- chart_data = ndb.TextProperty()
- dt = ndb.DateTimeProperty(auto_now=True)
- class highest_score(ndb.Model):
- score = ndb.TextProperty()
- @classmethod
- def return_current_highest(cls):
- s = memcache.get('largest_ever')
- if s is None:
- x = highest_score.get_or_insert('current_highest')
- score = x.score
- if score is None:
- memcache.set('largest_ever',0)
- return 0
- else:
- memcache.set('largest_ever',int(score))
- return int(score)
- else:
- return s
- @classmethod
- def set_new_highest_score(cls,score):
- x = highest_score.get_or_insert('current_highest') # todo hmm.
- saved_highest = x.score
- if saved_highest is None:
- x.score = str(score)
- x.put()
- memcache.set('largest_ever',int(score))
- saved_highest = x.score
- if int(saved_highest)<score:
- x.score = str(score)
- x.put()
- c = score_history()
- c.chart_data= str(score)
- c.put()
- memcache.set('largest_ever',int(score))
- class current_round_data(ndb.Model):
- data = ndb.PickleProperty()
- # todo track two strings side by side marking changes as you go, as tool.
- def create_new_generation():
- memcache_data = memcache.get('saved_round_data')
- if memcache_data is None:
- saved_data = current_round_data.get_or_insert('saved_round_data')
- else:
- saved_data = memcache_data
- sorted_candidate_list = make_ten_generations(saved_data.data)
- sorted_candidate_list = sorted(sorted_candidate_list,key=operator.itemgetter(1)) # sort by the score in the tuple
- sorted_candidate_list.reverse() # reverse it so that the highest score is first
- 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
- highest_score.set_new_highest_score(winner)
- saved_data.data=sorted_candidate_list
- d= saved_data.data
- saved_data.put()
- memcache.set('saved_round_data',saved_data)
- class generations(webapp.RequestHandler):
- def get(self):
- memcache_data = memcache.get('saved_round_data')
- if memcache_data is None:
- saved_data = current_round_data.get_or_insert('saved_round_data')
- if saved_data.data is None:
- create_new_generation()
- self.redirect('/')
- return
- else:
- saved_data = memcache_data.data
- render_details(self,saved_data)
- def make_ten_generations(saved_data=None):
- sc = simple_counter.get_or_insert('just_the_one')
- sc.counter+=1 # update the counters only when we make a new generation
- sc.put()
- if saved_data is None:
- data = play_a_round() # generate a list ['H','H','T',...]
- else:
- n = []
- for d, score in saved_data:
- n.append(d)
- data = n # use what we're passed
- #todo this sucks
- candidate_list = determine_score(data) #score the data by creating a tuple with the data in postion 0 and the score in position 1
- i = 0
- while i<1:
- candidate_list=new_generation(candidate_list)
- i+=1
- return candidate_list
- class MainHandler(webapp.RequestHandler):
- def get(self):
- create_new_generation()
- def render_details(self,sorted_candidate_list):
- sc = simple_counter.get_or_insert('just_the_one')
- memd = get('prerendered_data'+str(sc.counter))
- if memd:
- self.response.out.write(memd)
- return
- 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
- s = []
- if winner > 10**60:
- s.append("we have a winner with a score of {0}".format(winner))
- else:
- 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>'
- 'This is iteration {3}<br> Refresh the page in a minute to see the next generation.'
- 'Highest score this round {0}<br>'
- 'Which is<br>{1}<br>away from the target of <br>'
- '{2}'
- ''
- ''.format(winner,10**60-winner,10**60,sc.counter))
- s.append('<br>Largest score generated so far: {0}'.format(highest_score.return_current_highest()))
- table = render_table(sorted_candidate_list)
- ss = ''.join(s)
- sss = ss + table
- set('prerendered_data'+str(sc.counter),sss)
- self.response.out.write(sss)
- #todo graph score over time.
- def render_table(current_round_list_of_tuples):
- t = HTML.Table(header_row=['Score'])
- try:
- for i, (data, score) in enumerate(current_round_list_of_tuples):
- colored_data = []
- for toss in data:
- if toss =='H':
- colored_data.append(HTML.TableCell('H', bgcolor='green'))
- else:
- colored_data.append(HTML.TableCell('T', bgcolor='grey'))
- x = [score]
- x.extend(colored_data)
- t.rows.append(x)
- except ValueError:
- pass
- htmlcode = str(t)
- return htmlcode
- def split_list(alist, wanted_parts=1):
- length = len(alist)
- return [alist[i * length // wanted_parts: (i + 1) * length // wanted_parts]
- for i in range(wanted_parts)]
- def determine_score(list_list_of_tosses):
- round_score = []
- for r in list_list_of_tosses:
- counter = 0
- score = []
- for toss in r:
- if toss == 'H':
- # As they do so, they record all runs of heads
- counter+=1
- if toss == 'T':
- # so that if they toss H T T H H H T H T T H H H H T T T,
- if counter > 0:
- # they will record: 1, 3, 1, 4, representing the number of heads in each run.
- score.append(counter)
- counter = 0
- round_score.append(score)
- final_scores = []
- for i, player_scores in enumerate(round_score):
- # At the end of each round, each player computes the product of their runs-of-heads.
- final_scores.append((list_list_of_tosses[i],reduce(mul,player_scores))) # keep the scores and the list together via a tuple
- return final_scores
- def point_mutate(a_list):
- new_list = a_list[:]
- for i, toss in enumerate(a_list):
- counter = random.randint(0,100)
- if counter > 90:
- new_list[i] = (random.choice(['H','T'])) # generate a new value
- return new_list
- def play_a_round():
- round = []
- for t in range(PLAYERS):
- # On each turn, players toss a fair coin 500 times.
- player_round = []
- for p in range(TOSS):
- player_round.append(random.choice(['H','T']))
- round.append(player_round)
- return round
- def new_generation(sorted_candidate_list):
- l = len(sorted_candidate_list)
- half = l/2
- sorted_candidate_list = sorted(sorted_candidate_list,key=operator.itemgetter(1)) # sort by the score in the tuple
- sorted_candidate_list.reverse()
- without_bottom_50 = sorted_candidate_list[:half]
- new_50_items = []
- try:
- for existing_item, score in without_bottom_50:
- new_string = point_mutate(existing_item)
- new_50_items.append(new_string)
- except ValueError:
- pass
- data_only = []
- for data, score in without_bottom_50: # get rid of the tuple score now.
- data_only.append(data)
- data_only.extend(new_50_items)
- new_scored_list = determine_score(data_only)
- return new_scored_list
- def delete(key):
- chunk_keys = memcache.get(key)
- if chunk_keys is None:
- return False
- chunk_keys.append(key)
- memcache.delete_multi(chunk_keys)
- return True
- def set(key, value):
- pickled_value = pickle.dumps(value)
- # delete previous entity with the given key
- # in order to conserve available memcache space.
- delete(key)
- pickled_value_size = len(pickled_value)
- chunk_keys = []
- for pos in range(0, pickled_value_size, MEMCACHE_MAX_ITEM_SIZE):
- # TODO: use memcache.set_multi() for speedup, but don't forget
- # about batch operation size limit (32Mb currently).
- chunk = pickled_value[pos:pos + MEMCACHE_MAX_ITEM_SIZE]
- # the pos is used for reliable distinction between chunk keys.
- # the random suffix is used as a counter-measure for distinction
- # between different values, which can be simultaneously written
- # under the same key.
- chunk_key = '%s%d%d' % (key, pos, random.getrandbits(31))
- is_success = memcache.set(chunk_key, chunk)
- if not is_success:
- return False
- chunk_keys.append(chunk_key)
- return memcache.set(key, chunk_keys)
- def get(key):
- chunk_keys = memcache.get(key)
- if chunk_keys is None:
- return None
- chunks = []
- for chunk_key in chunk_keys:
- # TODO: use memcache.get_multi() for speedup.
- # Don't forget about the batch operation size limit (currently 32Mb).
- chunk = memcache.get(chunk_key)
- if chunk is None:
- return None
- chunks.append(chunk)
- pickled_value = ''.join(chunks)
- try:
- return pickle.loads(pickled_value)
- except Exception:
- return None
- app = webapp.WSGIApplication([
- ('/random', MainHandler) ,
- ('/', generations)
- ],
- debug=True)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement