-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathTributeNarrative.py
118 lines (98 loc) · 3.34 KB
/
TributeNarrative.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
'''
Generate a narrative from TributeModel data
Overall concept: find local extrema in the time series of actor wealth; subset
extrema based on importance. The region between each two remaining extrema is
an era. Count events occuring between those points to create a narrative for
that era.
'''
from collections import defaultdict
import random
import string
import numpy as np
from extrema import rank_extrema
syllables = []
vowels = "aeiouy"
for a in vowels:
for b in string.ascii_letters:
if b in vowels: continue
syllables.append(a+b)
syllables.append(b+a)
def make_word(syl_count=3):
word = "".join([random.choice(syllables) for i in range(syl_count)])
if len(word) > 2 and random.random() < 0.5:
word = word[:-1]
return word.title()
def get_eras(data):
#data = np.array(actor.wealth_history)
pt_rank = rank_extrema(data)
ranks = list(pt_rank["min"].values()) + list(pt_rank["max"].values())
x_pts = [0, len(data)-1]
cutoff = np.median(ranks)
for x, count in pt_rank["max"].items():
if count >= cutoff:
x_pts.append(x)
for x, count in pt_rank["min"].items():
if count >= cutoff:
x_pts.append(x)
x_pts = sorted(x_pts)
eras = [(x_pts[i], x_pts[i+1]) for i in range(len(x_pts)-1)]
return eras
def write_era(agent, era):
data = np.array(agent.wealth_history)
start, end = era
dt = end - start
delta = data[end] - data[start]
text = "From {} to {}, {} saw ".format(start, end, agent.name)
# Categorize the era
if abs(delta)/dt < np.std(np.diff(data)):
text += "slow "
else:
text += "rapid "
if delta < 0:
text += "decline. "
else:
text += "growth. "
# Get events
event_counts = defaultdict(lambda: defaultdict(int))
for event in agent.log:
if era[0] < event[0] <= era[1]:
event_type = event[1]
event_target = event[2]
event_counts[event_type][event_target] += 1
war_count = len(event_counts["Led war against"])
war_targets = list_to_words(list(event_counts["Led war against"].keys()))
joined_wars = sum(list(event_counts["Joined war against"].values()))
tributes = list(event_counts["Receive tribute"].keys())
tributes_txt = list_to_words(tributes)
if war_count + joined_wars + len(tributes) == 0:
return text
if dt > 1:
text += "In this period it"
else:
text += "In {} it".format(end)
if war_count == 1:
text += " fought a war against {}".format(war_targets)
elif war_count > 1:
text += " fought {} wars against {}".format(war_count, war_targets)
if joined_wars > 0:
if len(tributes) == 0:
text += ", and "
if joined_wars == 1:
text += "joined its allies in one battle"
else:
text += "joined its allies in {} battles".format(joined_wars)
if len(tributes) > 0:
if war_count > 0 or joined_wars > 0:
text += " and"
text += " received tributes from {}".format(tributes_txt)
text += "."
return text
def list_to_words(values):
if len(values) == 0:
return "nobody"
if len(values) == 1:
return str(values[0])
else:
text = ", ".join(str(v) for v in values[:-1])
text += " and {}".format(values[-1])
return text