Skip to content

Commit 6cb4d69

Browse files
author
crawl
committed
Add milestone table, unify game and milestone db inserts, set up points for games worshipping different gods.
git-svn-id: svn+ssh://crawl.akrasiac.org/usr/local/crawlsvn@174 42476179-f906-4ffd-81fe-f88aabc8fb63
1 parent 40135fe commit 6cb4d69

File tree

7 files changed

+225
-45
lines changed

7 files changed

+225
-45
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
TAGS
12
*.swp
23
*.pyc
34
cao-*

TODO09

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
1-
Test code on 0.4 logfile (so we have lots of games)
2-
Rewire scripts to use 0.5 logfile once everything's tested and ok.
1+
Legend: ] done + tested
2+
* done, not tested
3+
4+
- Add new scoring rules.
5+
- New milestones for Crawl:
6+
god.worship <- Worshipping a new god
7+
god.renounce <- Renouncing an existing god.
8+
- Update list of uniques.
9+
- Update list of combos.
10+
- Test code on 0.4 logfile (so we have lots of games)
11+
- Rewire scripts to use 0.5 logfile once everything's tested and ok.
312

413
Trophies for 2009:
514

615
WINS:
716
----
8-
100 points for first win. (Since winning is kind of the goal.)
9-
50 points for second win that is not a repeat race or class.
10-
10 points for each win thereafter, repeat or not.
11-
50 extra points for your first all-rune victory.
12-
100 extra points for each consecutive win that is not a repeat race or class.
13-
30 extra points for each consecutive win that is a repeat race xor class.
14-
10 extra points for each consecutive win that is a repeat race and class.
15-
30 extra points for each non-consecutive win that is not a repeat race or
17+
]100 points for first win. (Since winning is kind of the goal.)
18+
]50 points for second win that is not a repeat race or class.
19+
]10 points for each win thereafter, repeat or not.
20+
]50 extra points for your first all-rune victory.
21+
]100 extra points for each consecutive win that is not a repeat race or class.
22+
]30 extra points for each consecutive win that is a repeat race xor class.
23+
]10 extra points for each consecutive win that is a repeat race and class.
24+
]30 extra points for each non-consecutive win that is not a repeat race or
1625
class.
17-
10 extra points for each non-consecutive win that is a repeat race xor class.
26+
]10 extra points for each non-consecutive win that is a repeat race xor class.
1827

19-
20 extra points for each win with a new god (including "No God"). This does
20-
not apply if you changed gods during the game.
28+
*20 extra points for each win with a new god (including "No God").
29+
This does not apply if you changed gods during the game.
2130

22-
For streak wins, "Repeat" means "in that streak;" for non-streak wins,
23-
"repeat" means "ever."
31+
(For streak wins, "Repeat" means "in that streak;" for non-streak
32+
wins, "repeat" means "ever.")
2433

2534
SPECIAL WINS
2635
------------

database.sql

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
DROP TABLE IF EXISTS players;
2+
DROP TABLE IF EXISTS milestones;
23
DROP TABLE IF EXISTS teams;
34
DROP TABLE IF EXISTS milestone_bookmark;
45
DROP TABLE IF EXISTS games;
@@ -56,6 +57,8 @@ CREATE TABLE teams (
5657

5758
-- For mappings of logfile fields to columns, see loaddb.py
5859
CREATE TABLE games (
60+
id BIGINT AUTO_INCREMENT,
61+
5962
-- Source logfile
6063
source_file VARCHAR(150),
6164
-- Offset in the source file.
@@ -84,7 +87,7 @@ CREATE TABLE games (
8487
maxhp INT,
8588
maxmaxhp INT,
8689
strength INT,
87-
intellegence INT,
90+
intelligence INT,
8891
dexterity INT,
8992
god CHAR(20),
9093
duration INT,
@@ -102,9 +105,11 @@ CREATE TABLE games (
102105
verb_msg VARCHAR(255),
103106
nrune INT DEFAULT 0,
104107

105-
CONSTRAINT PRIMARY KEY (source_file, source_file_offset)
108+
CONSTRAINT PRIMARY KEY (id)
106109
);
107110

111+
CREATE INDEX games_source_offset ON games (source_file, source_file_offset);
112+
108113
CREATE INDEX games_kgrp ON games (kgroup);
109114
CREATE INDEX games_ktyp ON games (killertype);
110115
CREATE INDEX games_p_ktyp ON games (player, killertype);
@@ -115,6 +120,63 @@ CREATE INDEX games_win_dur ON games (killertype, duration);
115120
-- Index to help us find fastest wins (turncount) quick.
116121
CREATE INDEX games_win_turn ON games (killertype, turn);
117122

123+
CREATE TABLE milestones (
124+
id BIGINT AUTO_INCREMENT PRIMARY KEY,
125+
-- Source milestone file
126+
source_file VARCHAR(150),
127+
128+
-- The actual game that this milestone is linked with.
129+
game_id BIGINT,
130+
131+
version VARCHAR(10),
132+
cv VARCHAR(10),
133+
player VARCHAR(20),
134+
race VARCHAR(20),
135+
raceabbr CHAR(2) NOT NULL,
136+
class VARCHAR(20),
137+
charabbrev CHAR(4),
138+
xl INT,
139+
skill VARCHAR(16),
140+
sk_lev INT,
141+
title VARCHAR(50),
142+
place VARCHAR(16),
143+
144+
branch VARCHAR(16),
145+
lvl INT,
146+
ltyp VARCHAR(16),
147+
hp INT,
148+
maxhp INT,
149+
maxmaxhp INT,
150+
strength INT,
151+
intelligence INT,
152+
dexterity INT,
153+
god VARCHAR(50),
154+
duration BIGINT,
155+
turn BIGINT,
156+
runes INT,
157+
nrune INT,
158+
159+
-- Game start time.
160+
start_time DATETIME,
161+
162+
-- Milestone time.
163+
milestone_time DATETIME,
164+
165+
-- Known milestones: abyss.enter, abyss.exit, rune, orb, ghost, uniq,
166+
-- uniq.ban, br.enter, br.end.
167+
verb VARCHAR(20),
168+
noun VARCHAR(100),
169+
170+
-- The actual milestone message.
171+
milestone VARCHAR(255),
172+
173+
FOREIGN KEY (game_id) REFERENCES games (id)
174+
ON DELETE SET NULL
175+
);
176+
177+
-- To find milestones belonging to a particular game.
178+
CREATE INDEX milestone_lookup_by_time ON milestones (player, start_time, verb);
179+
118180
-- A table to keep track of the last milestone we've processed. This
119181
-- will have only one row for one filename.
120182
CREATE TABLE milestone_bookmark (

loaddb.py

Lines changed: 92 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,6 @@ def line(self, cursor):
192192
self.offset = newoffset
193193
else:
194194
xdict = apply_dbtypes( xlog_dict(line) )
195-
if xdict.get('time'):
196-
xdict['time'] = datetime.to_sql(xdict['time'])
197-
198195
xline = Xlogline( self, self.filename, self.offset,
199196
xdict.get('end') or xdict.get('time'),
200197
xdict, self.proc_op )
@@ -291,6 +288,28 @@ def xlog_set_killer_group(d):
291288

292289
d['kgroup'] = killer
293290

291+
def xlog_milestone_fixup(d):
292+
for field in [x for x in ['lv', 'uid'] if d.has_key(x)]:
293+
del d[field]
294+
verb = d['type']
295+
milestone = d['milestone']
296+
noun = None
297+
if verb == 'uniq':
298+
match = R_MILE_UNIQ.findall(milestone)
299+
if match[0][0] == 'banished':
300+
verb = 'uniq.ban'
301+
noun = match[0][1]
302+
if verb == 'ghost':
303+
match = R_MILE_GHOST.findall(milestone)
304+
if match[0][0] == 'banished':
305+
verb = 'ghost.ban'
306+
noun = match[0][1]
307+
if verb == 'rune':
308+
noun = R_RUNE.findall(milestone)[0]
309+
noun = noun or milestone
310+
d['verb'] = verb
311+
d['noun'] = noun
312+
294313
def xlog_dict(logline):
295314
d = parse_logline(logline.strip())
296315
# Fake a raceabbr field.
@@ -305,6 +324,8 @@ def xlog_dict(logline):
305324
d['nrune'] = d.get('nrune') or d.get('urune')
306325
d['urune'] = d.get('urune') or d.get('nrune')
307326

327+
if d.has_key('milestone'):
328+
xlog_milestone_fixup(d)
308329
xlog_set_killer_group(d)
309330

310331
return d
@@ -332,7 +353,7 @@ def xlog_dict(logline):
332353
[ 'mhp', 'maxhp' ],
333354
[ 'mmhp', 'maxmaxhp' ],
334355
[ 'str', 'strength' ],
335-
[ 'int', 'intellegence' ],
356+
[ 'int', 'intelligence' ],
336357
[ 'dex', 'dexterity' ],
337358
[ 'god', 'god' ],
338359
[ 'start', 'start_time' ],
@@ -350,13 +371,52 @@ def xlog_dict(logline):
350371
[ 'vmsg', 'verb_msg' ],
351372
[ 'kaux', 'kaux' ],
352373
[ 'nrune', 'nrune' ],
353-
[ 'urune', 'runes' ] ]
374+
[ 'urune', 'runes' ],
375+
]
376+
377+
MILE_DB_MAPPINGS = [
378+
[ 'v', 'version' ],
379+
[ 'lv', 'lv' ],
380+
[ 'name', 'player' ],
381+
[ 'uid', 'uid' ],
382+
[ 'race', 'race' ],
383+
[ 'raceabbr', 'raceabbr' ],
384+
[ 'cls', 'class' ],
385+
[ 'char', 'charabbrev' ],
386+
[ 'xl', 'xl' ],
387+
[ 'sk', 'skill' ],
388+
[ 'sklev', 'sk_lev' ],
389+
[ 'title', 'title' ],
390+
[ 'place', 'place' ],
391+
[ 'br', 'branch' ],
392+
[ 'lvl', 'lvl' ],
393+
[ 'ltyp', 'ltyp' ],
394+
[ 'hp', 'hp' ],
395+
[ 'mhp', 'maxhp' ],
396+
[ 'mmhp', 'maxmaxhp' ],
397+
[ 'str', 'strength' ],
398+
[ 'int', 'intelligence' ],
399+
[ 'dex', 'dexterity' ],
400+
[ 'god', 'god' ],
401+
[ 'start', 'start_time' ],
402+
[ 'dur', 'duration' ],
403+
[ 'turn', 'turn' ],
404+
[ 'dam', 'damage' ],
405+
[ 'piety', 'piety' ],
406+
[ 'nrune', 'nrune' ],
407+
[ 'urune', 'runes' ],
408+
[ 'time', 'milestone_time' ],
409+
]
354410

355411
LOGLINE_TO_DBFIELD = dict(LOG_DB_MAPPINGS)
412+
COMBINED_LOG_TO_DB = dict(LOG_DB_MAPPINGS + MILE_DB_MAPPINGS)
413+
356414
R_MONTH_FIX = re.compile(r'^(\d{4})(\d{2})(.*)')
357415
R_GHOST_NAME = re.compile(r"^(.*)'s? ghost")
358416
R_MILESTONE_GHOST_NAME = re.compile(r"the ghost of (.*) the ")
359417
R_KILL_UNIQUE = re.compile(r'^killed (.*)\.$')
418+
R_MILE_UNIQ = re.compile(r'^\w+ (.*)\.$')
419+
R_MILE_GHOST = re.compile(r'^\w+ the ghost of (\S+)')
360420
R_RUNE = re.compile(r"found an? (.*) rune")
361421
R_HYDRA = re.compile(r'^an? (\w+)-headed hydra')
362422

@@ -458,6 +518,7 @@ def count(self, cursor, msg=None, exc=Exception):
458518
'piety':sql_int,
459519
'penitence':sql_int,
460520
'end_time':datetime,
521+
'milestone_time':datetime,
461522
'terse_msg':varchar,
462523
'verb_msg':varchar,
463524
'nrune':sql_int,
@@ -546,33 +607,40 @@ def apply_dbtypes(game):
546607
(i.e. not in dbfield_to_sqltype) are ignored."""
547608
new_hash = { }
548609
for key, value in game.items():
549-
if LOGLINE_TO_DBFIELD.has_key(key):
550-
new_hash[key] = dbfield_to_sqltype[LOGLINE_TO_DBFIELD[key]].to_sql(value)
610+
if (COMBINED_LOG_TO_DB.has_key(key) and
611+
dbfield_to_sqltype.has_key(COMBINED_LOG_TO_DB[key])):
612+
new_hash[key] = dbfield_to_sqltype[COMBINED_LOG_TO_DB[key]].to_sql(value)
551613
else:
552614
new_hash[key] = value
553615
return new_hash
554616

555-
def make_games_insert_query(dbfields, filename, offset):
556-
fields = ["source_file", "source_file_offset"]
557-
values = [filename, offset]
558-
559-
for logkey, sqlkey in LOG_DB_MAPPINGS:
560-
if dbfields.has_key(logkey):
617+
def make_xlog_db_query(db_mappings, xdict, filename, offset, table):
618+
fields = ['source_file']
619+
values = [filename]
620+
if offset is not None and offset != False:
621+
fields.append('source_file_offset')
622+
values.append(offset)
623+
for logkey, sqlkey in db_mappings:
624+
if xdict.has_key(logkey):
561625
fields.append(sqlkey)
562-
values.append(dbfields[logkey])
563-
564-
return Query('INSERT INTO games (%s) VALUES (%s);' %
565-
(",".join(fields), ",".join([ "%s" for v in values])),
626+
values.append(xdict[logkey])
627+
return Query('INSERT INTO %s (%s) VALUES (%s);' %
628+
(table, ",".join(fields), ",".join([ "%s" for v in values])),
566629
*values)
567630

568-
def insert_logline(cursor, logdict, filename, offset):
569-
query = make_games_insert_query(logdict, filename, offset)
631+
def insert_xlog_db(cursor, xdict, filename, offset):
632+
milestone = xdict.has_key('milestone')
633+
db_mappings = milestone and MILE_DB_MAPPINGS or LOG_DB_MAPPINGS
634+
thingname = milestone and 'milestone' or 'logline'
635+
table = milestone and 'milestones' or 'games'
636+
save_offset = not milestone
637+
query = make_xlog_db_query(db_mappings, xdict, filename,
638+
save_offset and offset, table)
570639
try:
571640
query.execute(cursor)
572641
except Exception, e:
573-
error("Error inserting logline %s (query: %s [%s]): %s"
574-
% (logdict, query.query, query.values, e))
575-
raise
642+
error("Error inserting %s %s (query: %s [%s]): %s"
643+
% (thingname, milestone, query.query, query.values, e))
576644

577645
def dbfile_offset(cursor, table, filename):
578646
"""Given a db cursor and filename, returns the offset of the last
@@ -651,7 +719,7 @@ def process_log(cursor, filename, offset, d):
651719

652720
cursor.execute('BEGIN;')
653721
try:
654-
insert_logline(cursor, d, filename, offset)
722+
insert_xlog_db(cursor, d, filename, offset)
655723
if ghost_kill:
656724
record_ghost_kill(cursor, d)
657725

@@ -752,6 +820,7 @@ def add_milestone_record(c, filename, offset, d):
752820
c.execute('BEGIN;')
753821
try:
754822
update_milestone_bookmark(c, filename, offset)
823+
insert_xlog_db(c, d, filename, offset)
755824
handler = MILESTONE_HANDLERS.get(d['type'])
756825
if handler:
757826
handler(c, d)

outline.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ def repeat_race_class(previous_chars, char):
117117
repeats += 1
118118
return repeats
119119

120+
def is_god_repeated(previous_wins, g):
121+
"""Returns true if the god in the current game was already used by
122+
the player in a previous winning game. The gods checked are the gods
123+
at end of game."""
124+
def god(g):
125+
return g.get('god') or ''
126+
return god(g) in [god(x) for x in previous_wins]
127+
120128
def crunch_winner(c, game):
121129
"""A game that wins could assign a variety of irrevocable points for a
122130
variety of different things. This function needs to calculate them all."""
@@ -141,12 +149,19 @@ def crunch_winner(c, game):
141149
"nth_win:%d" % (previous_wins + 1),
142150
game['name'], get_points(previous_wins, 200, 100, 50))
143151

144-
my_wins = query.get_wins(c, player = game['name'], before = game['end'])
152+
my_wins = query.get_winning_games(c, player = game['name'],
153+
before = game['end'])
145154
n_my_wins = len(my_wins)
146155

156+
# Assign 20 extra points for winning with a god that you haven't used before.
157+
if not is_god_repeated(my_wins, game) and not query.did_change_god(game):
158+
god = (game.get('god') or 'atheist').lower()
159+
assign_points(c, "my_win_" + god, 20)
160+
147161
repeated = 0
148162
if n_my_wins > 0:
149-
repeated = repeat_race_class(my_wins, game['char'])
163+
repeated = repeat_race_class([x['charabbrev'] for x in my_wins],
164+
game['char'])
150165

151166
if n_my_wins == 0:
152167
# First win! I bet you don't have a streak

0 commit comments

Comments
 (0)