mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
* improved statistics
* improved tile support * misc. bugs fixes and improvements git-svn-id: https://pysolfc.svn.sourceforge.net/svnroot/pysolfc/PySolFC/trunk@81 39dd0a4e-7c14-0410-91b3-c4f2d318f732
This commit is contained in:
parent
e401d6a28e
commit
a4a25adbd9
15 changed files with 371 additions and 459 deletions
|
@ -6,7 +6,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PySol 0.0.1\n"
|
"Project-Id-Version: PySol 0.0.1\n"
|
||||||
"POT-Creation-Date: Sat Oct 7 20:02:33 2006\n"
|
"POT-Creation-Date: Sat Oct 7 20:02:33 2006\n"
|
||||||
"PO-Revision-Date: 2006-10-07 20:10+0400\n"
|
"PO-Revision-Date: 2006-10-08 18:43+0400\n"
|
||||||
"Last-Translator: Скоморох <skomoroh@gmail.com>\n"
|
"Last-Translator: Скоморох <skomoroh@gmail.com>\n"
|
||||||
"Language-Team: Russian <ru@li.org>\n"
|
"Language-Team: Russian <ru@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
@ -1430,7 +1430,7 @@ msgid "Intelligence +"
|
||||||
msgstr "Смекалка +"
|
msgstr "Смекалка +"
|
||||||
|
|
||||||
msgid "Interchange"
|
msgid "Interchange"
|
||||||
msgstr "Чередование"
|
msgstr "Перестановка"
|
||||||
|
|
||||||
msgid "Interment"
|
msgid "Interment"
|
||||||
msgstr "Погребение"
|
msgstr "Погребение"
|
||||||
|
|
|
@ -46,18 +46,16 @@ from settings import TOP_TITLE
|
||||||
from gamedb import GI
|
from gamedb import GI
|
||||||
|
|
||||||
# stats imports
|
# stats imports
|
||||||
from stats import PysolStatsFormatter
|
from stats import FileStatsFormatter
|
||||||
from pysoltk import SingleGame_StatsDialog, AllGames_StatsDialog
|
from pysoltk import SingleGame_StatsDialog, AllGames_StatsDialog
|
||||||
from pysoltk import FullLog_StatsDialog, SessionLog_StatsDialog
|
from pysoltk import FullLog_StatsDialog, SessionLog_StatsDialog
|
||||||
from pysoltk import Status_StatsDialog, Top_StatsDialog
|
from pysoltk import Status_StatsDialog, Top_StatsDialog
|
||||||
from pysoltk import GameInfoDialog
|
from pysoltk import GameInfoDialog
|
||||||
|
|
||||||
# toolkit imports
|
# toolkit imports
|
||||||
from pysoltk import EVENT_HANDLED, EVENT_PROPAGATE
|
|
||||||
from pysoltk import MfxMessageDialog, MfxSimpleEntry
|
from pysoltk import MfxMessageDialog, MfxSimpleEntry
|
||||||
from pysoltk import MfxExceptionDialog
|
from pysoltk import MfxExceptionDialog
|
||||||
from pysoltk import PlayerOptionsDialog
|
from pysoltk import PlayerOptionsDialog
|
||||||
#from pysoltk import HintOptionsDialog
|
|
||||||
from pysoltk import TimeoutsDialog
|
from pysoltk import TimeoutsDialog
|
||||||
from pysoltk import ColorsDialog
|
from pysoltk import ColorsDialog
|
||||||
from pysoltk import FontsDialog
|
from pysoltk import FontsDialog
|
||||||
|
@ -533,7 +531,7 @@ class PysolMenubarActions:
|
||||||
# Game menu - statistics
|
# Game menu - statistics
|
||||||
#
|
#
|
||||||
|
|
||||||
def _mStatsSave(self, player, header, filename, write_method):
|
def _mStatsSave(self, player, filename, write_method):
|
||||||
file = None
|
file = None
|
||||||
if player is None:
|
if player is None:
|
||||||
text = _("Demo statistics")
|
text = _("Demo statistics")
|
||||||
|
@ -544,10 +542,8 @@ class PysolMenubarActions:
|
||||||
filename = os.path.normpath(filename)
|
filename = os.path.normpath(filename)
|
||||||
try:
|
try:
|
||||||
file = open(filename, "a")
|
file = open(filename, "a")
|
||||||
a = PysolStatsFormatter(self.app)
|
a = FileStatsFormatter(self.app, file)
|
||||||
writer = a.FileWriter(file)
|
write_method(a, player)
|
||||||
apply(write_method, (a, writer, player, header))
|
|
||||||
destruct(a)
|
|
||||||
except EnvError, ex:
|
except EnvError, ex:
|
||||||
if file: file.close()
|
if file: file.close()
|
||||||
d = MfxExceptionDialog(self.top, ex,
|
d = MfxExceptionDialog(self.top, ex,
|
||||||
|
@ -597,19 +593,16 @@ class PysolMenubarActions:
|
||||||
d = GameInfoDialog(self.top, header, self.app)
|
d = GameInfoDialog(self.top, header, self.app)
|
||||||
elif mode == 202:
|
elif mode == 202:
|
||||||
# print stats to file
|
# print stats to file
|
||||||
header = _("Statistics for ") + p0
|
write_method = FileStatsFormatter.writeStats
|
||||||
write_method = PysolStatsFormatter.writeStats
|
self._mStatsSave(player, "stats", write_method)
|
||||||
self._mStatsSave(player, header, "stats", write_method)
|
|
||||||
elif mode == 203:
|
elif mode == 203:
|
||||||
# print full log to file
|
# print full log to file
|
||||||
header = _("Full log for ") + p0
|
write_method = FileStatsFormatter.writeFullLog
|
||||||
write_method = PysolStatsFormatter.writeFullLog
|
self._mStatsSave(player, "log", write_method)
|
||||||
self._mStatsSave(player, header, "log", write_method)
|
|
||||||
elif mode == 204:
|
elif mode == 204:
|
||||||
# print session log to file
|
# print session log to file
|
||||||
header = _("Session log for ") + p0
|
write_method = FileStatsFormatter.writeSessionLog
|
||||||
write_method = PysolStatsFormatter.writeSessionLog
|
self._mStatsSave(player, "log", write_method)
|
||||||
self._mStatsSave(player, header, "log", write_method)
|
|
||||||
elif mode == 301:
|
elif mode == 301:
|
||||||
# reset all player stats
|
# reset all player stats
|
||||||
if self.game.areYouSure(_("Reset all statistics"),
|
if self.game.areYouSure(_("Reset all statistics"),
|
||||||
|
|
|
@ -143,10 +143,10 @@ class Options:
|
||||||
'startdrag' : True,
|
'startdrag' : True,
|
||||||
'turnwaste' : True,
|
'turnwaste' : True,
|
||||||
'undo' : True,
|
'undo' : True,
|
||||||
'gamefinished' : True,
|
'gamefinished' : False,
|
||||||
'gamelost' : True,
|
'gamelost' : False,
|
||||||
'gameperfect' : True,
|
'gameperfect' : False,
|
||||||
'gamewon' : True,
|
'gamewon' : False,
|
||||||
}
|
}
|
||||||
# fonts
|
# fonts
|
||||||
self.fonts = {"default" : None,
|
self.fonts = {"default" : None,
|
||||||
|
|
|
@ -778,8 +778,6 @@ class Game:
|
||||||
def _defaultHandler(self):
|
def _defaultHandler(self):
|
||||||
self.interruptSleep()
|
self.interruptSleep()
|
||||||
self.deleteStackDesc()
|
self.deleteStackDesc()
|
||||||
if self.demo:
|
|
||||||
self.stopDemo()
|
|
||||||
|
|
||||||
def clickHandler(self, event):
|
def clickHandler(self, event):
|
||||||
self._defaultHandler()
|
self._defaultHandler()
|
||||||
|
@ -789,6 +787,9 @@ class Game:
|
||||||
def undoHandler(self, event):
|
def undoHandler(self, event):
|
||||||
if not self.app: return EVENT_PROPAGATE # FIXME (GTK)
|
if not self.app: return EVENT_PROPAGATE # FIXME (GTK)
|
||||||
self._defaultHandler()
|
self._defaultHandler()
|
||||||
|
if self.demo:
|
||||||
|
self.stopDemo()
|
||||||
|
return
|
||||||
if self.app.opt.mouse_undo and not self.event_handled:
|
if self.app.opt.mouse_undo and not self.event_handled:
|
||||||
self.app.menubar.mUndo()
|
self.app.menubar.mUndo()
|
||||||
self.event_handled = False
|
self.event_handled = False
|
||||||
|
@ -797,6 +798,9 @@ class Game:
|
||||||
def redoHandler(self, event):
|
def redoHandler(self, event):
|
||||||
if not self.app: return EVENT_PROPAGATE # FIXME (GTK)
|
if not self.app: return EVENT_PROPAGATE # FIXME (GTK)
|
||||||
self._defaultHandler()
|
self._defaultHandler()
|
||||||
|
if self.demo:
|
||||||
|
self.stopDemo()
|
||||||
|
return
|
||||||
if self.app.opt.mouse_undo and not self.event_handled:
|
if self.app.opt.mouse_undo and not self.event_handled:
|
||||||
self.app.menubar.mRedo()
|
self.app.menubar.mRedo()
|
||||||
self.event_handled = False
|
self.event_handled = False
|
||||||
|
|
|
@ -132,7 +132,7 @@ class Strata(Game):
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
s.rows.append(AC_RowStack(x, y, self, max_move=1, max_accept=1))
|
s.rows.append(AC_RowStack(x, y, self, max_move=1, max_accept=1))
|
||||||
x = x + l.XS
|
x = x + l.XS
|
||||||
s.talon = RedealTalonStack(l.XM, l.YM, self, max_rounds=2)
|
s.talon = RedealTalonStack(l.XM, l.YM, self, max_rounds=3)
|
||||||
|
|
||||||
# define stack-groups
|
# define stack-groups
|
||||||
l.defaultStackGroups()
|
l.defaultStackGroups()
|
||||||
|
@ -157,6 +157,6 @@ registerGame(GameInfo(293, Nationale, "Nationale",
|
||||||
GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL,
|
GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 0, GI.SL_MOSTLY_SKILL,
|
||||||
altnames=('Zigzag Course',) ))
|
altnames=('Zigzag Course',) ))
|
||||||
registerGame(GameInfo(606, Strata, "Strata",
|
registerGame(GameInfo(606, Strata, "Strata",
|
||||||
GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 1, GI.SL_MOSTLY_SKILL,
|
GI.GT_BAKERS_DOZEN | GI.GT_OPEN, 2, 2, GI.SL_MOSTLY_SKILL,
|
||||||
ranks=(0, 6, 7, 8, 9, 10, 11, 12) ))
|
ranks=(0, 6, 7, 8, 9, 10, 11, 12) ))
|
||||||
|
|
||||||
|
|
|
@ -693,18 +693,20 @@ class Octagon(Game):
|
||||||
i = 0
|
i = 0
|
||||||
for x, y in ((l.XM+w1, l.YM),
|
for x, y in ((l.XM+w1, l.YM),
|
||||||
(l.XM+w1+l.XS, l.YM),
|
(l.XM+w1+l.XS, l.YM),
|
||||||
(l.XM+w1-2*l.XS-l.XM, l.YM+l.YS),
|
(l.XM+w1-2*l.XS-l.XS/2-l.XM, l.YM+l.YS),
|
||||||
(l.XM+w1-l.XS-l.XM, l.YM+l.YS),
|
(l.XM+w1-l.XS-l.XS/2-l.XM, l.YM+l.YS),
|
||||||
(l.XM+w1+2*l.XS+l.XM, l.YM+l.YS),
|
(l.XM+w1+2*l.XS+l.XS/2+l.XM, l.YM+l.YS),
|
||||||
(l.XM+w1+3*l.XS+l.XM, l.YM+l.YS),
|
(l.XM+w1+3*l.XS+l.XS/2+l.XM, l.YM+l.YS),
|
||||||
(l.XM+w1, l.YM+2*l.YS),
|
(l.XM+w1, l.YM+2*l.YS),
|
||||||
(l.XM+w1+l.XS, l.YM+2*l.YS),):
|
(l.XM+w1+l.XS, l.YM+2*l.YS),):
|
||||||
s.foundations.append(SS_FoundationStack(x, y, self, suit=i%4))
|
s.foundations.append(SS_FoundationStack(x, y, self, suit=i%4))
|
||||||
i += 1
|
i += 1
|
||||||
x, y = l.XM+w1, l.YM+l.YS
|
x, y = l.XM+w1, l.YM+l.YS
|
||||||
s.talon = WasteTalonStack(x, y, self, max_rounds=4)
|
s.talon = WasteTalonStack(x, y, self, max_rounds=4)
|
||||||
|
l.createText(s.talon, 'nw')
|
||||||
x += l.XS
|
x += l.XS
|
||||||
s.waste = WasteStack(x, y, self)
|
s.waste = WasteStack(x, y, self)
|
||||||
|
l.createText(s.waste, 'ne')
|
||||||
|
|
||||||
l.defaultStackGroups()
|
l.defaultStackGroups()
|
||||||
|
|
||||||
|
|
|
@ -596,6 +596,10 @@ class Toad(Game):
|
||||||
# // Shifting
|
# // Shifting
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
|
class Shifting_Hint(Numerica_Hint):
|
||||||
|
shallMovePile = DefaultHint._cautiousShallMovePile
|
||||||
|
|
||||||
|
|
||||||
class Shifting_RowStack(Numerica_RowStack):
|
class Shifting_RowStack(Numerica_RowStack):
|
||||||
def acceptsCards(self, from_stack, cards):
|
def acceptsCards(self, from_stack, cards):
|
||||||
if not BasicRowStack.acceptsCards(self, from_stack, cards):
|
if not BasicRowStack.acceptsCards(self, from_stack, cards):
|
||||||
|
@ -611,6 +615,7 @@ class Shifting_RowStack(Numerica_RowStack):
|
||||||
|
|
||||||
|
|
||||||
class Shifting(Numerica):
|
class Shifting(Numerica):
|
||||||
|
Hint_Class = Shifting_Hint
|
||||||
RowStack_Class = StackWrapper(Shifting_RowStack, max_accept=1)
|
RowStack_Class = StackWrapper(Shifting_RowStack, max_accept=1)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -415,10 +415,8 @@ class Carpet(Game):
|
||||||
# // British Constitution
|
# // British Constitution
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
class BritishConstitution_RowStack(AC_RowStack):
|
class BritishConstitution_RowStackMethods:
|
||||||
def acceptsCards(self, from_stack, cards):
|
def acceptsCards(self, from_stack, cards):
|
||||||
if not AC_RowStack.acceptsCards(self, from_stack, cards):
|
|
||||||
return False
|
|
||||||
if self in self.game.s.rows[:8] and from_stack in self.game.s.rows[8:16]:
|
if self in self.game.s.rows[:8] and from_stack in self.game.s.rows[8:16]:
|
||||||
return True
|
return True
|
||||||
if self in self.game.s.rows[8:16] and from_stack in self.game.s.rows[16:24]:
|
if self in self.game.s.rows[8:16] and from_stack in self.game.s.rows[16:24]:
|
||||||
|
@ -429,6 +427,18 @@ class BritishConstitution_RowStack(AC_RowStack):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
class BritishConstitution_RowStack(BritishConstitution_RowStackMethods, AC_RowStack):
|
||||||
|
def acceptsCards(self, from_stack, cards):
|
||||||
|
if not AC_RowStack.acceptsCards(self, from_stack, cards):
|
||||||
|
return False
|
||||||
|
return BritishConstitution_RowStackMethods.acceptsCards(self, from_stack, cards)
|
||||||
|
|
||||||
|
class NewBritishConstitution_RowStack(BritishConstitution_RowStackMethods, RK_RowStack):
|
||||||
|
def acceptsCards(self, from_stack, cards):
|
||||||
|
if not RK_RowStack.acceptsCards(self, from_stack, cards):
|
||||||
|
return False
|
||||||
|
return BritishConstitution_RowStackMethods.acceptsCards(self, from_stack, cards)
|
||||||
|
|
||||||
|
|
||||||
class BritishConstitution_Foundation(SS_FoundationStack):
|
class BritishConstitution_Foundation(SS_FoundationStack):
|
||||||
def acceptsCards(self, from_stack, cards):
|
def acceptsCards(self, from_stack, cards):
|
||||||
|
@ -500,8 +510,7 @@ class BritishConstitution(Game):
|
||||||
|
|
||||||
|
|
||||||
class NewBritishConstitution(BritishConstitution):
|
class NewBritishConstitution(BritishConstitution):
|
||||||
RowStack_Class = StackWrapper(BritishConstitution_RowStack, base_rank=JACK)
|
RowStack_Class = StackWrapper(NewBritishConstitution_RowStack, base_rank=JACK)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
|
|
|
@ -40,61 +40,71 @@ gettext = _
|
||||||
# //
|
# //
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
class StatsWriter(PysolStatsFormatter.StringWriter):
|
class StatsFormatter(PysolStatsFormatter):
|
||||||
|
|
||||||
def __init__(self, store):
|
def __init__(self, app, store):
|
||||||
|
self.app = app
|
||||||
self.store = store
|
self.store = store
|
||||||
|
|
||||||
def p(self, s):
|
def writeStats(self, player, sort_by='name'):
|
||||||
pass
|
for result in self.getStatResults(player, sort_by):
|
||||||
|
iter = self.store.append(None)
|
||||||
def pheader(self, s):
|
self.store.set(iter,
|
||||||
pass
|
0, gettext(result[0]),
|
||||||
|
1, result[1],
|
||||||
def pstats(self, *args, **kwargs):
|
2, result[2],
|
||||||
gameid=kwargs.get('gameid', None)
|
3, result[3],
|
||||||
if gameid is None:
|
4, result[4],
|
||||||
# header
|
5, result[5],
|
||||||
return
|
6, result[6],
|
||||||
|
7, result[7])
|
||||||
|
total, played, won, lost, time, moves, perc = self.getStatSummary()
|
||||||
|
text = _("Total (%d out of %d games)") % (played, total)
|
||||||
iter = self.store.append(None)
|
iter = self.store.append(None)
|
||||||
self.store.set(iter,
|
self.store.set(iter,
|
||||||
0, gettext(args[0]),
|
0, text,
|
||||||
1, args[1],
|
1, won+lost,
|
||||||
2, args[2],
|
2, won,
|
||||||
3, args[3],
|
3, lost,
|
||||||
4, args[4],
|
4, time,
|
||||||
5, args[5],
|
5, moves,
|
||||||
6, args[6],
|
6, perc,
|
||||||
7, gameid)
|
7, -1)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
class LogWriter(PysolStatsFormatter.StringWriter):
|
class LogFormatter(PysolStatsFormatter):
|
||||||
MAX_ROWS = 10000
|
MAX_ROWS = 10000
|
||||||
|
|
||||||
def __init__(self, store):
|
def __init__(self, app, store):
|
||||||
|
self.app = app
|
||||||
self.store = store
|
self.store = store
|
||||||
self._num_rows = 0
|
self._num_rows = 0
|
||||||
|
|
||||||
def p(self, s):
|
def writeLog(self, player, prev_games):
|
||||||
pass
|
if not player or not prev_games:
|
||||||
|
return 0
|
||||||
|
num_rows = 0
|
||||||
|
for result in self.getLogResults(player, prev_games):
|
||||||
|
iter = self.store.append(None)
|
||||||
|
self.store.set(iter,
|
||||||
|
0, gettext(result[0]),
|
||||||
|
1, result[1],
|
||||||
|
2, result[2],
|
||||||
|
3, result[3],
|
||||||
|
4, result[4])
|
||||||
|
num_rows += 1
|
||||||
|
if num_rows > self.MAX_ROWS:
|
||||||
|
break
|
||||||
|
return 1
|
||||||
|
|
||||||
def pheader(self, s):
|
def writeFullLog(self, player):
|
||||||
pass
|
prev_games = self.app.stats.prev_games.get(player)
|
||||||
|
return self.writeLog(player, prev_games)
|
||||||
|
|
||||||
def plog(self, gamename, gamenumber, date, status, gameid=-1, won=-1):
|
def writeSessionLog(self, player):
|
||||||
if gameid < 0:
|
prev_games = self.app.stats.session_games.get(player)
|
||||||
# header
|
return self.writeLog(player, prev_games)
|
||||||
return
|
|
||||||
if self._num_rows > self.MAX_ROWS:
|
|
||||||
return
|
|
||||||
iter = self.store.append(None)
|
|
||||||
self.store.set(iter,
|
|
||||||
0, gettext(gamename),
|
|
||||||
1, gamenumber,
|
|
||||||
2, date,
|
|
||||||
3, status,
|
|
||||||
4, gameid)
|
|
||||||
self._num_rows += 1
|
|
||||||
|
|
||||||
|
|
||||||
class Game_StatsDialog:
|
class Game_StatsDialog:
|
||||||
|
@ -107,7 +117,6 @@ class Game_StatsDialog:
|
||||||
self.games = {}
|
self.games = {}
|
||||||
self.games_id = [] # sorted by name
|
self.games_id = [] # sorted by name
|
||||||
#
|
#
|
||||||
formatter = PysolStatsFormatter(self.app)
|
|
||||||
glade_file = app.dataloader.findFile('pysolfc.glade')
|
glade_file = app.dataloader.findFile('pysolfc.glade')
|
||||||
#
|
#
|
||||||
games = app.gdb.getGamesIdSortedByName()
|
games = app.gdb.getGamesIdSortedByName()
|
||||||
|
@ -142,16 +151,16 @@ class Game_StatsDialog:
|
||||||
self._updateTop(gameid)
|
self._updateTop(gameid)
|
||||||
# all games stat
|
# all games stat
|
||||||
store = self._createStatsList()
|
store = self._createStatsList()
|
||||||
writer = StatsWriter(store)
|
formatter = StatsFormatter(app, store)
|
||||||
formatter.writeStats(writer, player, header, sort_by='name')
|
formatter.writeStats(player)
|
||||||
# full log
|
# full log
|
||||||
store = self._createLogList('full_log_treeview')
|
store = self._createLogList('full_log_treeview')
|
||||||
writer = LogWriter(store)
|
formatter = LogFormatter(app, store)
|
||||||
formatter.writeFullLog(writer, player, header)
|
formatter.writeFullLog(player)
|
||||||
# session log
|
# session log
|
||||||
store = self._createLogList('session_log_treeview')
|
store = self._createLogList('session_log_treeview')
|
||||||
writer = LogWriter(store)
|
formatter = LogFormatter(app, store)
|
||||||
formatter.writeSessionLog(writer, player, header)
|
formatter.writeSessionLog(player)
|
||||||
#
|
#
|
||||||
self._translateLabels()
|
self._translateLabels()
|
||||||
dialog = self.widgets_tree.get_widget('stats_dialog')
|
dialog = self.widgets_tree.get_widget('stats_dialog')
|
||||||
|
|
|
@ -38,69 +38,28 @@
|
||||||
import os, sys, time, types
|
import os, sys, time, types
|
||||||
|
|
||||||
# PySol imports
|
# PySol imports
|
||||||
from mfxutil import SubclassResponsibility, Struct, destruct
|
|
||||||
from mfxutil import format_time
|
from mfxutil import format_time
|
||||||
from settings import PACKAGE, VERSION
|
from settings import PACKAGE, VERSION
|
||||||
from gamedb import GI
|
from gamedb import GI
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# // FIXME - this a quick hack and needs a rewrite
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# //
|
# //
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
class PysolStatsFormatter:
|
class PysolStatsFormatter:
|
||||||
def __init__(self, app):
|
|
||||||
self.app = app
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
class StringWriter:
|
|
||||||
def __init__(self):
|
|
||||||
self.text = ""
|
|
||||||
|
|
||||||
def p(self, s):
|
|
||||||
self.text = self.text + s
|
|
||||||
|
|
||||||
def nl(self, count=1):
|
|
||||||
self.p("\n" * count)
|
|
||||||
|
|
||||||
def pheader(self, s):
|
|
||||||
self.p(s)
|
|
||||||
|
|
||||||
def pstats(self, *args, **kwargs):
|
|
||||||
s = "%-30s %7s %7s %7s %7s %7s %7s\n" % args
|
|
||||||
self.p(s)
|
|
||||||
|
|
||||||
def plog(self, gamename, gamenumber, date, status, gameid=-1, won=-1):
|
|
||||||
self.p("%-25s %-20s %17s %s\n" % (gamename, gamenumber, date, status))
|
|
||||||
|
|
||||||
|
|
||||||
class FileWriter(StringWriter):
|
def getStatHeader(self):
|
||||||
def __init__(self, file):
|
return (_("Game"),
|
||||||
self.file = file
|
_("Played"),
|
||||||
|
_("Won"),
|
||||||
|
_("Lost"),
|
||||||
|
_('Playing time'),
|
||||||
|
_('Moves'),
|
||||||
|
_("% won"))
|
||||||
|
|
||||||
def p(self, s):
|
def getStatResults(self, player, sort_by='name'):
|
||||||
self.file.write(s.encode('utf-8'))
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
def writeHeader(self, writer, header, pagewidth=72):
|
|
||||||
date = time.ctime(time.time())
|
|
||||||
date = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()))
|
|
||||||
blanks = max(pagewidth - len(header) - len(date), 1)
|
|
||||||
writer.pheader(header + " "*blanks + date + "\n")
|
|
||||||
writer.pheader("-" * pagewidth + "\n")
|
|
||||||
writer.pheader("\n")
|
|
||||||
|
|
||||||
def writeStats(self, writer, player, header, sort_by='name'):
|
|
||||||
app = self.app
|
app = self.app
|
||||||
#
|
#
|
||||||
sort_functions = {
|
sort_functions = {
|
||||||
|
@ -113,18 +72,8 @@ class PysolStatsFormatter:
|
||||||
'percent': app.getGamesIdSortedByPercent,
|
'percent': app.getGamesIdSortedByPercent,
|
||||||
}
|
}
|
||||||
sort_func = sort_functions[sort_by]
|
sort_func = sort_functions[sort_by]
|
||||||
|
|
||||||
self.writeHeader(writer, header, 62)
|
|
||||||
writer.pstats(player or _("Demo games"),
|
|
||||||
_("Played"),
|
|
||||||
_("Won"),
|
|
||||||
_("Lost"),
|
|
||||||
_('Playing time'),
|
|
||||||
_('Moves'),
|
|
||||||
_("% won"))
|
|
||||||
writer.nl()
|
|
||||||
twon, tlost, tgames, ttime, tmoves = 0, 0, 0, 0, 0
|
|
||||||
g = sort_func()
|
g = sort_func()
|
||||||
|
twon, tlost, tgames, ttime, tmoves = 0, 0, 0, 0, 0
|
||||||
for id in g:
|
for id in g:
|
||||||
name = app.getGameTitleName(id)
|
name = app.getGameTitleName(id)
|
||||||
#won, lost = app.stats.getStats(player, id)
|
#won, lost = app.stats.getStats(player, id)
|
||||||
|
@ -134,33 +83,43 @@ class PysolStatsFormatter:
|
||||||
if won + lost > 0: perc = "%.1f" % (100.0 * won / (won + lost))
|
if won + lost > 0: perc = "%.1f" % (100.0 * won / (won + lost))
|
||||||
else: perc = "0.0"
|
else: perc = "0.0"
|
||||||
if won > 0 or lost > 0 or id == app.game.id:
|
if won > 0 or lost > 0 or id == app.game.id:
|
||||||
#writer.pstats(name, won+lost, won, lost, perc, gameid=id)
|
|
||||||
t = format_time(time)
|
t = format_time(time)
|
||||||
m = str(round(moves, 1))
|
m = str(round(moves, 1))
|
||||||
writer.pstats(name, won+lost, won, lost, t, m, perc, gameid=id)
|
yield [name, won+lost, won, lost, t, m, perc, id]
|
||||||
tgames = tgames + 1
|
tgames = tgames + 1
|
||||||
writer.nl()
|
|
||||||
won, lost = twon, tlost
|
won, lost = twon, tlost
|
||||||
if won + lost > 0:
|
if won + lost > 0:
|
||||||
if won > 0:
|
if won > 0:
|
||||||
time = format_time(ttime/won)
|
time = format_time(ttime/tgames)
|
||||||
moves = round(tmoves/won, 1)
|
moves = round(tmoves/tgames, 1)
|
||||||
else:
|
else:
|
||||||
time = format_time(0)
|
time = format_time(0)
|
||||||
moves = 0
|
moves = 0
|
||||||
perc = "%.1f" % (100.0*won/(won+lost))
|
perc = "%.1f" % (100.0*won/(won+lost))
|
||||||
else: perc = "0.0"
|
else: perc = "0.0"
|
||||||
writer.pstats(_("Total (%d out of %d games)") % (tgames, len(g)),
|
self.total_games = len(g)
|
||||||
won+lost, won, lost, time, moves, perc)
|
self.played_games = tgames
|
||||||
writer.nl(2)
|
self.won_games = won
|
||||||
return tgames
|
self.lost_games = lost
|
||||||
|
self.avrg_time = time
|
||||||
|
self.avrg_moves = moves
|
||||||
|
self.percent = perc
|
||||||
|
#yield (_("Total (%d out of %d games)") % (tgames, len(g)),
|
||||||
|
# won+lost, won, lost, time, moves, perc, '')
|
||||||
|
|
||||||
def _writeLog(self, writer, player, header, prev_games):
|
def getStatSummary(self):
|
||||||
if not player or not prev_games:
|
return self.total_games, \
|
||||||
return 0
|
self.played_games, \
|
||||||
self.writeHeader(writer, header, 71)
|
self.won_games, \
|
||||||
writer.plog(_("Game"), _("Game number"), _("Started at"), _("Status"))
|
self.lost_games, \
|
||||||
writer.nl()
|
self.avrg_time, \
|
||||||
|
self.avrg_moves, \
|
||||||
|
self.percent
|
||||||
|
|
||||||
|
def getLogHeader(self):
|
||||||
|
return _("Game"), _("Game number"), _("Started at"), _("Status")
|
||||||
|
|
||||||
|
def getLogResults(self, player, prev_games):
|
||||||
twon, tlost = 0, 0
|
twon, tlost = 0, 0
|
||||||
for pg in prev_games:
|
for pg in prev_games:
|
||||||
if type(pg) is not types.TupleType:
|
if type(pg) is not types.TupleType:
|
||||||
|
@ -198,14 +157,88 @@ class PysolStatsFormatter:
|
||||||
status = "*error*"
|
status = "*error*"
|
||||||
if -2 <= pg[2] <= 2:
|
if -2 <= pg[2] <= 2:
|
||||||
status = (_("Loaded"), _("Not won"), _("Lost"), _("Won"), _("Perfect")) [pg[2]+2]
|
status = (_("Loaded"), _("Not won"), _("Lost"), _("Won"), _("Perfect")) [pg[2]+2]
|
||||||
writer.plog(name, gamenumber, date, status, gameid=gameid, won=pg[2])
|
#writer.plog(name, gamenumber, date, status, gameid=gameid, won=pg[2])
|
||||||
writer.nl(2)
|
yield [name, gamenumber, date, status, pg[2], gameid]
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
def writeStats(self, player, sort_by='name'):
|
||||||
|
pass
|
||||||
|
def writeFullLog(self, player):
|
||||||
|
pass
|
||||||
|
def writeSessionLog(self, player):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FileStatsFormatter(PysolStatsFormatter):
|
||||||
|
|
||||||
|
def __init__(self, app, file):
|
||||||
|
self.app = app
|
||||||
|
self.file = file
|
||||||
|
|
||||||
|
def p(self, s):
|
||||||
|
self.file.write(s.encode('utf-8'))
|
||||||
|
|
||||||
|
def nl(self, count=1):
|
||||||
|
self.p("\n" * count)
|
||||||
|
|
||||||
|
def pheader(self, s):
|
||||||
|
self.p(s)
|
||||||
|
|
||||||
|
def pstats(self, *args, **kwargs):
|
||||||
|
s = "%-30s %7s %7s %7s %7s %7s %7s\n" % args
|
||||||
|
self.p(s)
|
||||||
|
|
||||||
|
def plog(self, gamename, gamenumber, date, status, gameid=-1, won=-1):
|
||||||
|
self.p("%-25s %-20s %17s %s\n" % (gamename, gamenumber, date, status))
|
||||||
|
|
||||||
|
def writeHeader(self, header, pagewidth=72):
|
||||||
|
date = time.ctime(time.time())
|
||||||
|
date = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()))
|
||||||
|
blanks = max(pagewidth - len(header) - len(date), 1)
|
||||||
|
self.pheader(header + " "*blanks + date + "\n")
|
||||||
|
self.pheader("-" * pagewidth + "\n")
|
||||||
|
self.pheader("\n")
|
||||||
|
|
||||||
|
def writeStats(self, player, sort_by='name'):
|
||||||
|
header = _("Statistics for ") + player
|
||||||
|
self.writeHeader(header, 62)
|
||||||
|
header = self.getStatHeader()
|
||||||
|
self.pstats(*header)
|
||||||
|
self.nl()
|
||||||
|
for result in self.getStatResults(player, sort_by):
|
||||||
|
gameid = result.pop()
|
||||||
|
self.pstats(gameid=gameid, *result)
|
||||||
|
self.nl()
|
||||||
|
total, played, won, lost, time, moves, perc = self.getStatSummary()
|
||||||
|
self.pstats(_("Total (%d out of %d games)") % (played, total),
|
||||||
|
won+lost, won, lost, time, moves, perc)
|
||||||
|
self.nl(2)
|
||||||
|
return played
|
||||||
|
|
||||||
|
def writeLog(self, player, header, prev_games):
|
||||||
|
if not player or not prev_games:
|
||||||
|
return 0
|
||||||
|
self.writeHeader(header, 71)
|
||||||
|
header = self.getLogHeader()
|
||||||
|
self.plog(*header)
|
||||||
|
self.nl()
|
||||||
|
for result in self.getLogResults(player, prev_games):
|
||||||
|
gameid = result.pop()
|
||||||
|
won = result.pop()
|
||||||
|
self.plog(gameid=gameid, won=won, *result)
|
||||||
|
self.nl(2)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
def writeFullLog(self, writer, player, header):
|
def writeFullLog(self, player):
|
||||||
|
header = _("Full log for ") + player
|
||||||
prev_games = self.app.stats.prev_games.get(player)
|
prev_games = self.app.stats.prev_games.get(player)
|
||||||
return self._writeLog(writer, player, header, prev_games)
|
return self.writeLog(player, header, prev_games)
|
||||||
|
|
||||||
def writeSessionLog(self, writer, player, header):
|
def writeSessionLog(self, player):
|
||||||
|
header = _("Session log for ") + player
|
||||||
prev_games = self.app.stats.session_games.get(player)
|
prev_games = self.app.stats.session_games.get(player)
|
||||||
return self._writeLog(writer, player, header, prev_games)
|
return self.writeLog(player, header, prev_games)
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,8 @@ class PysolProgressBar:
|
||||||
return
|
return
|
||||||
self.percent = min(100, max(0, self.percent))
|
self.percent = min(100, max(0, self.percent))
|
||||||
self.progress.config(value=self.percent)
|
self.progress.config(value=self.percent)
|
||||||
self.top.update_idletasks()
|
##self.top.update_idletasks()
|
||||||
|
self.top.update()
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
|
|
|
@ -54,7 +54,8 @@ __all__ = ['tkversion',
|
||||||
|
|
||||||
# imports
|
# imports
|
||||||
import sys, os
|
import sys, os
|
||||||
import Tile as Tkinter
|
import traceback
|
||||||
|
import Tkinter
|
||||||
|
|
||||||
# Toolkit imports
|
# Toolkit imports
|
||||||
|
|
||||||
|
@ -73,6 +74,7 @@ try:
|
||||||
tkversion = tuple(m[:4])
|
tkversion = tuple(m[:4])
|
||||||
del m
|
del m
|
||||||
except:
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# experimental
|
# experimental
|
||||||
|
|
|
@ -80,12 +80,7 @@ class SingleGame_StatsDialog(MfxDialog):
|
||||||
self.top.wm_minsize(200, 200)
|
self.top.wm_minsize(200, 200)
|
||||||
self.button = kw.default
|
self.button = kw.default
|
||||||
#
|
#
|
||||||
##createChart = self.create3DBarChart
|
|
||||||
createChart = self.createPieChart
|
createChart = self.createPieChart
|
||||||
##createChart = self.createSimpleChart
|
|
||||||
## if parent.winfo_screenwidth() < 800 or parent.winfo_screenheight() < 600:
|
|
||||||
## createChart = self.createPieChart
|
|
||||||
## createChart = self.createSimpleChart
|
|
||||||
#
|
#
|
||||||
self.font = self.app.getFont("default")
|
self.font = self.app.getFont("default")
|
||||||
self.tk_font = tkFont.Font(self.top, self.font)
|
self.tk_font = tkFont.Font(self.top, self.font)
|
||||||
|
@ -177,79 +172,6 @@ class SingleGame_StatsDialog(MfxDialog):
|
||||||
c.create_text(x, ty[1]-dy, text="%d%%" % (100-pw), anchor="ne", font=tfont, fill=fg)
|
c.create_text(x, ty[1]-dy, text="%d%%" % (100-pw), anchor="ne", font=tfont, fill=fg)
|
||||||
|
|
||||||
|
|
||||||
## def _createChart3DBar(self, canvas, perc, x, y, p, col):
|
|
||||||
## if perc < 0.005:
|
|
||||||
## return
|
|
||||||
## # translate and scale
|
|
||||||
## p = list(p[:])
|
|
||||||
## for i in (0, 1, 2, 3):
|
|
||||||
## p[i] = (x + p[i][0], y + p[i][1])
|
|
||||||
## j = i + 4
|
|
||||||
## dx = int(round(p[j][0] * perc))
|
|
||||||
## dy = int(round(p[j][1] * perc))
|
|
||||||
## p[j] = (p[i][0] + dx, p[i][1] + dy)
|
|
||||||
## # draw rects
|
|
||||||
## def draw_rect(a, b, c, d, col, canvas=canvas, p=p):
|
|
||||||
## points = (p[a][0], p[a][1], p[b][0], p[b][1],
|
|
||||||
## p[c][0], p[c][1], p[d][0], p[d][1])
|
|
||||||
## canvas.create_polygon(points, fill=col)
|
|
||||||
## draw_rect(0, 1, 5, 4, col[0])
|
|
||||||
## draw_rect(1, 2, 6, 5, col[1])
|
|
||||||
## draw_rect(4, 5, 6, 7, col[2])
|
|
||||||
## # draw lines
|
|
||||||
## def draw_line(a, b, canvas=canvas, p=p):
|
|
||||||
## ##print a, b, p[a], p[b]
|
|
||||||
## canvas.create_line(p[a][0], p[a][1], p[b][0], p[b][1])
|
|
||||||
## draw_line(0, 1)
|
|
||||||
## draw_line(1, 2)
|
|
||||||
## draw_line(0, 4)
|
|
||||||
## draw_line(1, 5)
|
|
||||||
## draw_line(2, 6)
|
|
||||||
## ###draw_line(3, 7) ## test
|
|
||||||
## draw_line(4, 5)
|
|
||||||
## draw_line(5, 6)
|
|
||||||
## draw_line(6, 7)
|
|
||||||
## draw_line(7, 4)
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# charts
|
|
||||||
#
|
|
||||||
|
|
||||||
## def createSimpleChart(self, app, won, lost, text):
|
|
||||||
## #c, tfont, fg = self._createChartInit(frame, 300, 100, text)
|
|
||||||
## self._createChartInit(300, 100, text)
|
|
||||||
## c, tfont, fg = self.canvas, self.font, self.fg
|
|
||||||
## #
|
|
||||||
## tx = (90, 180, 210)
|
|
||||||
## ty = (21, 41, 75)
|
|
||||||
## self._createChartTexts(tx, ty, won, lost)
|
|
||||||
|
|
||||||
## def create3DBarChart(self, app, won, lost, text):
|
|
||||||
## image = app.gimages.stats[0]
|
|
||||||
## iw, ih = image.width(), image.height()
|
|
||||||
## #c, tfont, fg = self._createChartInit(frame, iw+160, ih, text)
|
|
||||||
## self._createChartInit(iw+160, ih, text)
|
|
||||||
## c, tfont, fg = self.canvas, self.font, self.fg
|
|
||||||
## pwon, plost = self._getPwon(won, lost)
|
|
||||||
## #
|
|
||||||
## tx = (iw+20, iw+110, iw+140)
|
|
||||||
## yy = ih/2 ## + 7
|
|
||||||
## ty = (yy+21-46, yy+41-46, yy+75-46)
|
|
||||||
## #
|
|
||||||
## c.create_image(0, 7, image=image, anchor="nw")
|
|
||||||
## #
|
|
||||||
## p = ((0, 0), (44, 6), (62, -9), (20, -14),
|
|
||||||
## (-3, -118), (-1, -120), (-1, -114), (-4, -112))
|
|
||||||
## col = ("#00ff00", "#008200", "#00c300")
|
|
||||||
## self._createChart3DBar(c, pwon, 102, 145+7, p, col)
|
|
||||||
## p = ((0, 0), (49, 6), (61, -10), (15, -15),
|
|
||||||
## (1, -123), (3, -126), (4, -120), (1, -118))
|
|
||||||
## col = ("#ff0000", "#860400", "#c70400")
|
|
||||||
## self._createChart3DBar(c, plost, 216, 159+7, p, col)
|
|
||||||
## #
|
|
||||||
## self._createChartTexts(tx, ty, won, lost)
|
|
||||||
## c.create_text(tx[0], ty[0]-48, text=self.player, anchor="nw", font=tfont, fill=fg)
|
|
||||||
|
|
||||||
def createPieChart(self, app, won, lost, text):
|
def createPieChart(self, app, won, lost, text):
|
||||||
#c, tfont, fg = self._createChartInit(frame, 300, 100, text)
|
#c, tfont, fg = self._createChartInit(frame, 300, 100, text)
|
||||||
|
@ -300,8 +222,11 @@ class SingleGame_StatsDialog(MfxDialog):
|
||||||
# //
|
# //
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
class TreeWriter(PysolStatsFormatter.StringWriter):
|
class TreeFormatter(PysolStatsFormatter):
|
||||||
def __init__(self, tree, parent_window, font, w, h):
|
MAX_ROWS = 10000
|
||||||
|
|
||||||
|
def __init__(self, app, tree, parent_window, font, w, h):
|
||||||
|
self.app = app
|
||||||
self.tree = tree
|
self.tree = tree
|
||||||
self.parent_window = parent_window
|
self.parent_window = parent_window
|
||||||
self.font = font
|
self.font = font
|
||||||
|
@ -311,12 +236,6 @@ class TreeWriter(PysolStatsFormatter.StringWriter):
|
||||||
self.w = w
|
self.w = w
|
||||||
self.h = h
|
self.h = h
|
||||||
|
|
||||||
def p(self, s):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def pheader(self, s):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _calc_tabs(self, arg):
|
def _calc_tabs(self, arg):
|
||||||
if self.parent_window.tree_tabs:
|
if self.parent_window.tree_tabs:
|
||||||
self._tabs = self.parent_window.tree_tabs
|
self._tabs = self.parent_window.tree_tabs
|
||||||
|
@ -331,57 +250,73 @@ class TreeWriter(PysolStatsFormatter.StringWriter):
|
||||||
self._tabs.append(10)
|
self._tabs.append(10)
|
||||||
self.parent_window.tree_tabs = self._tabs
|
self.parent_window.tree_tabs = self._tabs
|
||||||
|
|
||||||
def pstats(self, *args, **kwargs):
|
def writeStats(self, player, sort_by='name'):
|
||||||
header = False
|
header = self.getStatHeader()
|
||||||
if self._tabs is None:
|
if self._tabs is None:
|
||||||
# header
|
self._calc_tabs(header)
|
||||||
self._calc_tabs(args)
|
t1, t2, t3, t4, t5, t6, t7 = header
|
||||||
header = True
|
for column, text, anchor, tab in (
|
||||||
|
('#0', t1, 'nw', self._tabs[0]),
|
||||||
|
('played', t2, 'ne', self._tabs[1]),
|
||||||
|
('won', t3, 'ne', self._tabs[2]),
|
||||||
|
('lost', t4, 'ne', self._tabs[3]),
|
||||||
|
('time', t5, 'ne', self._tabs[4]),
|
||||||
|
('moves', t6, 'ne', self._tabs[5]),
|
||||||
|
('percent', t7, 'ne', self._tabs[6]), ):
|
||||||
|
self.tree.heading(column, text=text,
|
||||||
|
command=lambda par=self.parent_window, col=column: par.headerClick(col))
|
||||||
|
self.tree.column(column, width=tab)
|
||||||
|
|
||||||
t1, t2, t3, t4, t5, t6, t7 = args
|
for result in self.getStatResults(player, sort_by):
|
||||||
if not header: t1=gettext(t1) # game name
|
t1, t2, t3, t4, t5, t6, t7, t8 = result
|
||||||
|
t1=gettext(t1) # game name
|
||||||
if header:
|
|
||||||
for column, text, anchor, tab in (
|
|
||||||
('#0', t1, 'nw', self._tabs[0]),
|
|
||||||
('played', t2, 'ne', self._tabs[1]),
|
|
||||||
('won', t3, 'ne', self._tabs[2]),
|
|
||||||
('lost', t4, 'ne', self._tabs[3]),
|
|
||||||
('time', t5, 'ne', self._tabs[4]),
|
|
||||||
('moves', t6, 'ne', self._tabs[5]),
|
|
||||||
('percent', t7, 'ne', self._tabs[6]), ):
|
|
||||||
self.tree.heading(column, text=text,
|
|
||||||
command=lambda par=self.parent_window, col=column: par.headerClick(col))
|
|
||||||
self.tree.column(column, width=tab)
|
|
||||||
else:
|
|
||||||
id = self.tree.insert(None, "end", text=t1,
|
id = self.tree.insert(None, "end", text=t1,
|
||||||
values=(t2, t3, t4, t5, t6, t7))
|
values=(t2, t3, t4, t5, t6, t7))
|
||||||
self.parent_window.tree_items.append(id)
|
self.parent_window.tree_items.append(id)
|
||||||
|
|
||||||
def plog(self, *args, **kwargs):
|
total, played, won, lost, time, moves, perc = self.getStatSummary()
|
||||||
header = False
|
text = _("Total (%d out of %d games)") % (played, total)
|
||||||
|
id = self.tree.insert(None, "end", text=text,
|
||||||
|
values=(won+lost, won, lost, time, moves, perc))
|
||||||
|
self.parent_window.tree_items.append(id)
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def writeLog(self, player, prev_games):
|
||||||
if self._tabs is None:
|
if self._tabs is None:
|
||||||
# header
|
|
||||||
self._calc_tabs(('', '99999999999999999999', '9999-99-99 99:99', 'XXXXXXXXXXXX'))
|
self._calc_tabs(('', '99999999999999999999', '9999-99-99 99:99', 'XXXXXXXXXXXX'))
|
||||||
header = True
|
header = self.getLogHeader()
|
||||||
|
t1, t2, t3, t4 = header
|
||||||
t1, t2, t3, t4 = args[:4]
|
for column, text, anchor, tab in (
|
||||||
if not header: t1=gettext(t1) # game name
|
('#0', t1, 'nw', self._tabs[0]),
|
||||||
|
('gamenumber', t2, 'ne', self._tabs[1]),
|
||||||
if header:
|
('date', t3, 'ne', self._tabs[2]),
|
||||||
for column, text, anchor, tab in (
|
('status', t4, 'ne', self._tabs[3]), ):
|
||||||
('#0', t1, 'nw', self._tabs[0]),
|
self.tree.heading(column, text=text,
|
||||||
('gamenumber', t2, 'ne', self._tabs[1]),
|
command=lambda par=self.parent_window, col=column: par.headerClick(col))
|
||||||
('date', t3, 'ne', self._tabs[2]),
|
self.tree.column(column, width=tab)
|
||||||
('status', t4, 'ne', self._tabs[3]), ):
|
##if column in ('gamenumber', 'date', 'status'):
|
||||||
self.tree.heading(column, text=text,
|
## self.tree.column(column, anchor='center')
|
||||||
command=lambda par=self.parent_window, col=column: par.headerClick(col))
|
if not player or not prev_games:
|
||||||
self.tree.column(column, width=tab)
|
return 0
|
||||||
##if column in ('gamenumber', 'date', 'status'):
|
num_rows = 0
|
||||||
## self.tree.column(column, anchor='center')
|
for result in self.getLogResults(player, prev_games):
|
||||||
else:
|
t1, t2, t3, t4, t5, t6 = result
|
||||||
|
t1=gettext(t1) # game name
|
||||||
id = self.tree.insert(None, "end", text=t1, values=(t2, t3, t4))
|
id = self.tree.insert(None, "end", text=t1, values=(t2, t3, t4))
|
||||||
self.parent_window.tree_items.append(id)
|
self.parent_window.tree_items.append(id)
|
||||||
|
num_rows += 1
|
||||||
|
if num_rows > self.MAX_ROWS:
|
||||||
|
break
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def writeFullLog(self, player):
|
||||||
|
prev_games = self.app.stats.prev_games.get(player)
|
||||||
|
return self.writeLog(player, prev_games)
|
||||||
|
|
||||||
|
def writeSessionLog(self, player):
|
||||||
|
prev_games = self.app.stats.session_games.get(player)
|
||||||
|
return self.writeLog(player, prev_games)
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
|
@ -467,14 +402,9 @@ class AllGames_StatsDialog(MfxDialog):
|
||||||
if self.tree_items:
|
if self.tree_items:
|
||||||
self.tree.delete(tuple(self.tree_items))
|
self.tree.delete(tuple(self.tree_items))
|
||||||
self.tree_items = []
|
self.tree_items = []
|
||||||
a = PysolStatsFormatter(self.app)
|
formatter = TreeFormatter(self.app, self.tree, self,
|
||||||
writer = TreeWriter(self.tree, self,
|
|
||||||
self.font, self.CHAR_W, self.CHAR_H)
|
self.font, self.CHAR_W, self.CHAR_H)
|
||||||
if not a.writeStats(writer, player, header, sort_by=self.sort_by):
|
formatter.writeStats(player, sort_by=self.sort_by)
|
||||||
# FIXME
|
|
||||||
pass
|
|
||||||
destruct(writer)
|
|
||||||
destruct(a)
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
|
@ -487,13 +417,9 @@ class FullLog_StatsDialog(AllGames_StatsDialog):
|
||||||
COLUMNS = ('gamenumber', 'date', 'status')
|
COLUMNS = ('gamenumber', 'date', 'status')
|
||||||
|
|
||||||
def fillCanvas(self, player, header):
|
def fillCanvas(self, player, header):
|
||||||
a = PysolStatsFormatter(self.app)
|
formatter = TreeFormatter(self.app, self.tree, self, self.font,
|
||||||
writer = TreeWriter(self.tree, self, self.font,
|
self.CHAR_W, self.CHAR_H)
|
||||||
self.CHAR_W, self.CHAR_H)
|
formatter.writeFullLog(player)
|
||||||
if not a.writeFullLog(writer, player, header):
|
|
||||||
# FIXME
|
|
||||||
pass
|
|
||||||
destruct(a)
|
|
||||||
|
|
||||||
def initKw(self, kw):
|
def initKw(self, kw):
|
||||||
kw = KwStruct(kw,
|
kw = KwStruct(kw,
|
||||||
|
@ -509,13 +435,9 @@ class FullLog_StatsDialog(AllGames_StatsDialog):
|
||||||
|
|
||||||
class SessionLog_StatsDialog(FullLog_StatsDialog):
|
class SessionLog_StatsDialog(FullLog_StatsDialog):
|
||||||
def fillCanvas(self, player, header):
|
def fillCanvas(self, player, header):
|
||||||
a = PysolStatsFormatter(self.app)
|
formatter = TreeFormatter(self.app, self.tree, self, self.font,
|
||||||
writer = TreeWriter(self.tree, self, self.font,
|
self.CHAR_W, self.CHAR_H)
|
||||||
self.CHAR_W, self.CHAR_H)
|
formatter.writeSessionLog(player)
|
||||||
if not a.writeSessionLog(writer, player, header):
|
|
||||||
# FIXME
|
|
||||||
pass
|
|
||||||
destruct(a)
|
|
||||||
|
|
||||||
def initKw(self, kw):
|
def initKw(self, kw):
|
||||||
kw = KwStruct(kw,
|
kw = KwStruct(kw,
|
||||||
|
@ -582,8 +504,7 @@ class _TopDialog(MfxDialog):
|
||||||
self.createBitmaps(top_frame, kw)
|
self.createBitmaps(top_frame, kw)
|
||||||
|
|
||||||
cnf = {'master': top_frame,
|
cnf = {'master': top_frame,
|
||||||
'highlightthickness': 1,
|
'padding': (4, 1),
|
||||||
'highlightbackground': 'black',
|
|
||||||
}
|
}
|
||||||
frame = apply(Tkinter.Frame, (), cnf)
|
frame = apply(Tkinter.Frame, (), cnf)
|
||||||
frame.pack(expand=Tkinter.YES, fill=Tkinter.BOTH, padx=10, pady=10)
|
frame.pack(expand=Tkinter.YES, fill=Tkinter.BOTH, padx=10, pady=10)
|
||||||
|
@ -654,9 +575,9 @@ class Top_StatsDialog(MfxDialog):
|
||||||
app.stats.games_stats[player].has_key(gameid) and
|
app.stats.games_stats[player].has_key(gameid) and
|
||||||
app.stats.games_stats[player][gameid].time_result.top):
|
app.stats.games_stats[player][gameid].time_result.top):
|
||||||
|
|
||||||
Tkinter.Label(frame, text=_('Minimum')).grid(row=0, column=1)
|
Tkinter.Label(frame, text=_('Minimum')).grid(row=0, column=1, padx=4)
|
||||||
Tkinter.Label(frame, text=_('Maximum')).grid(row=0, column=2)
|
Tkinter.Label(frame, text=_('Maximum')).grid(row=0, column=2, padx=4)
|
||||||
Tkinter.Label(frame, text=_('Average')).grid(row=0, column=3)
|
Tkinter.Label(frame, text=_('Average')).grid(row=0, column=3, padx=4)
|
||||||
##Tkinter.Label(frame, text=_('Total')).grid(row=0, column=4)
|
##Tkinter.Label(frame, text=_('Total')).grid(row=0, column=4)
|
||||||
|
|
||||||
s = app.stats.games_stats[player][gameid]
|
s = app.stats.games_stats[player][gameid]
|
||||||
|
|
|
@ -297,7 +297,9 @@ class MfxTreeInCanvas(MfxScrolledCanvas):
|
||||||
# set scroll region
|
# set scroll region
|
||||||
bbox = self.canvas.bbox("all")
|
bbox = self.canvas.bbox("all")
|
||||||
##self.canvas.config(scrollregion=bbox)
|
##self.canvas.config(scrollregion=bbox)
|
||||||
self.canvas.config(scrollregion=(0,0,bbox[2],bbox[3]))
|
##self.canvas.config(scrollregion=(0,0,bbox[2],bbox[3]))
|
||||||
|
dx, dy = 8, 0 # margins
|
||||||
|
self.canvas.config(scrollregion=(-dx,-dy,bbox[2]+dx,bbox[3]+dy))
|
||||||
self.canvas.config(yscrollincrement=self.style.disty)
|
self.canvas.config(yscrollincrement=self.style.disty)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
|
|
|
@ -299,8 +299,9 @@ class SingleGame_StatsDialog(MfxDialog):
|
||||||
# //
|
# //
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
class CanvasWriter(PysolStatsFormatter.StringWriter):
|
class CanvasFormatter(PysolStatsFormatter):
|
||||||
def __init__(self, canvas, parent_window, font, w, h):
|
def __init__(self, app, canvas, parent_window, font, w, h):
|
||||||
|
self.app = app
|
||||||
self.canvas = canvas
|
self.canvas = canvas
|
||||||
self.parent_window = parent_window
|
self.parent_window = parent_window
|
||||||
##self.fg = canvas.cget("insertbackground")
|
##self.fg = canvas.cget("insertbackground")
|
||||||
|
@ -308,7 +309,7 @@ class CanvasWriter(PysolStatsFormatter.StringWriter):
|
||||||
self.font = font
|
self.font = font
|
||||||
self.w = w
|
self.w = w
|
||||||
self.h = h
|
self.h = h
|
||||||
self.x = self.y = 0
|
#self.x = self.y = 0
|
||||||
self.gameid = None
|
self.gameid = None
|
||||||
self.gamenumber = None
|
self.gamenumber = None
|
||||||
self.canvas.config(yscrollincrement=h)
|
self.canvas.config(yscrollincrement=h)
|
||||||
|
@ -317,26 +318,6 @@ class CanvasWriter(PysolStatsFormatter.StringWriter):
|
||||||
def _addItem(self, id):
|
def _addItem(self, id):
|
||||||
self.canvas.dialog.nodes[id] = (self.gameid, self.gamenumber)
|
self.canvas.dialog.nodes[id] = (self.gameid, self.gamenumber)
|
||||||
|
|
||||||
def p(self, s):
|
|
||||||
if self.y > 16000:
|
|
||||||
return
|
|
||||||
h1, h2 = 0, 0
|
|
||||||
while s and s[0] == "\n":
|
|
||||||
s = s[1:]
|
|
||||||
h1 = h1 + self.h
|
|
||||||
while s and s[-1] == "\n":
|
|
||||||
s = s[:-1]
|
|
||||||
h2 = h2 + self.h
|
|
||||||
self.y = self.y + h1
|
|
||||||
if s:
|
|
||||||
id = self.canvas.create_text(self.x, self.y, text=s, anchor="nw",
|
|
||||||
font=self.font, fill=self.fg)
|
|
||||||
self._addItem(id)
|
|
||||||
self.y = self.y + h2
|
|
||||||
|
|
||||||
def pheader(self, s):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _calc_tabs(self, arg):
|
def _calc_tabs(self, arg):
|
||||||
tw = 15*self.w
|
tw = 15*self.w
|
||||||
##tw = 160
|
##tw = 160
|
||||||
|
@ -347,59 +328,12 @@ class CanvasWriter(PysolStatsFormatter.StringWriter):
|
||||||
self._tabs.append(tw)
|
self._tabs.append(tw)
|
||||||
self._tabs.append(10)
|
self._tabs.append(10)
|
||||||
|
|
||||||
def pstats(self, *args, **kwargs):
|
def pstats(self, y, args, gameid=None):
|
||||||
gameid=kwargs.get('gameid', None)
|
x = 1
|
||||||
header = False
|
|
||||||
if self._tabs is None:
|
|
||||||
# header
|
|
||||||
header = True
|
|
||||||
self._calc_tabs(args)
|
|
||||||
self.gameid = 'header'
|
|
||||||
self.gamenumber = None
|
|
||||||
## if False:
|
|
||||||
## sort_by = ( 'name', 'played', 'won', 'lost',
|
|
||||||
## 'time', 'moves', 'percent', )
|
|
||||||
## frame = Tkinter.Frame(self.canvas)
|
|
||||||
## i = 0
|
|
||||||
## for t in args:
|
|
||||||
## w = self._tabs[i]
|
|
||||||
## if i == 0:
|
|
||||||
## w += 10
|
|
||||||
## b = Tkinter.Button(frame, text=t)
|
|
||||||
## b.grid(row=0, column=i, sticky='ew')
|
|
||||||
## b.bind('<1>', lambda e, f=self.parent_window.rearrange, s=sort_by[i]: f(s))
|
|
||||||
## frame.columnconfigure(i, minsize=w)
|
|
||||||
## i += 1
|
|
||||||
## self.canvas.create_window(0, 0, window=frame, anchor='nw')
|
|
||||||
## self.y += 20
|
|
||||||
## return
|
|
||||||
## if False:
|
|
||||||
## i = 0
|
|
||||||
## x = 0
|
|
||||||
## for t in args:
|
|
||||||
## w = self._tabs[i]
|
|
||||||
## h = 18
|
|
||||||
## anchor = 'ne'
|
|
||||||
## y = 0
|
|
||||||
## self.canvas.create_rectangle(x+2, y, x+w, y+h, width=1,
|
|
||||||
## fill="#00ff00", outline="#000000")
|
|
||||||
## x += w
|
|
||||||
## self.canvas.create_text(x-3, y+3, text=t, anchor=anchor)
|
|
||||||
## i += 1
|
|
||||||
## self.y += 20
|
|
||||||
## return
|
|
||||||
|
|
||||||
else:
|
|
||||||
self.gameid = gameid
|
|
||||||
self.gamenumber = None
|
|
||||||
if self.y > 16000:
|
|
||||||
return
|
|
||||||
x, y = 1, self.y
|
|
||||||
p = self._pstats_text
|
|
||||||
t1, t2, t3, t4, t5, t6, t7 = args
|
t1, t2, t3, t4, t5, t6, t7 = args
|
||||||
h = 0
|
self.gamenumber = None
|
||||||
if not header: t1=gettext(t1) # game name
|
if gameid is None: # header
|
||||||
|
self.gameid = 'header'
|
||||||
for var, text, anchor, tab in (
|
for var, text, anchor, tab in (
|
||||||
('name', t1, 'nw', self._tabs[0]+self._tabs[1]),
|
('name', t1, 'nw', self._tabs[0]+self._tabs[1]),
|
||||||
('played', t2, 'ne', self._tabs[2]),
|
('played', t2, 'ne', self._tabs[2]),
|
||||||
|
@ -408,46 +342,13 @@ class CanvasWriter(PysolStatsFormatter.StringWriter):
|
||||||
('time', t5, 'ne', self._tabs[5]),
|
('time', t5, 'ne', self._tabs[5]),
|
||||||
('moves', t6, 'ne', self._tabs[6]),
|
('moves', t6, 'ne', self._tabs[6]),
|
||||||
('percent', t7, 'ne', self._tabs[7]), ):
|
('percent', t7, 'ne', self._tabs[7]), ):
|
||||||
if header: self.gamenumber=var
|
if gameid is None: # header
|
||||||
h = max(h, p(x, y, anchor=anchor, text=text))
|
self.gamenumber=var
|
||||||
|
id = self.canvas.create_text(x, y, text=text, anchor=anchor,
|
||||||
|
font=self.font, fill=self.fg)
|
||||||
|
self._addItem(id)
|
||||||
x += tab
|
x += tab
|
||||||
|
|
||||||
self.pstats_perc(x, y, t7)
|
self.pstats_perc(x, y, t7)
|
||||||
self.y += h
|
|
||||||
self.gameid = None
|
|
||||||
return
|
|
||||||
|
|
||||||
## h = max(h, p(x, y, anchor="nw", text=t1))
|
|
||||||
## if header: self.gamenumber='played'
|
|
||||||
## x += self._tabs[0]+self._tabs[1]
|
|
||||||
## h = max(h, p(x, y, anchor="ne", text=t2))
|
|
||||||
## if header: self.gamenumber='won'
|
|
||||||
## x += self._tabs[2]
|
|
||||||
## h = max(h, p(x, y, anchor="ne", text=t3))
|
|
||||||
## if header: self.gamenumber='lost'
|
|
||||||
## x += self._tabs[3]
|
|
||||||
## h = max(h, p(x, y, anchor="ne", text=t4))
|
|
||||||
## if header: self.gamenumber='time'
|
|
||||||
## x += self._tabs[4]
|
|
||||||
## h = max(h, p(x, y, anchor="ne", text=t5))
|
|
||||||
## if header: self.gamenumber='moves'
|
|
||||||
## x += self._tabs[5]
|
|
||||||
## h = max(h, p(x, y, anchor="ne", text=t6))
|
|
||||||
## if header: self.gamenumber='percent'
|
|
||||||
## x += self._tabs[6]
|
|
||||||
## h = max(h, p(x, y, anchor="ne", text=t7))
|
|
||||||
## x += self._tabs[7]
|
|
||||||
## self.pstats_perc(x, y, t7)
|
|
||||||
## self.y += h
|
|
||||||
## self.gameid = None
|
|
||||||
|
|
||||||
def _pstats_text(self, x, y, **kw):
|
|
||||||
kwdefault(kw, font=self.font, fill=self.fg)
|
|
||||||
id = apply(self.canvas.create_text, (x, y), kw)
|
|
||||||
self._addItem(id)
|
|
||||||
return self.h
|
|
||||||
##bbox = self.canvas.bbox(id)
|
|
||||||
##return bbox[3] - bbox[1]
|
|
||||||
|
|
||||||
def pstats_perc(self, x, y, t):
|
def pstats_perc(self, x, y, t):
|
||||||
if not (t and "0" <= t[0] <= "9"):
|
if not (t and "0" <= t[0] <= "9"):
|
||||||
|
@ -498,13 +399,51 @@ class CanvasWriter(PysolStatsFormatter.StringWriter):
|
||||||
ix = ix + 8
|
ix = ix + 8
|
||||||
p = max(0.0, p - 0.1)
|
p = max(0.0, p - 0.1)
|
||||||
|
|
||||||
def plog(self, gamename, gamenumber, date, status, gameid=-1, won=-1):
|
def writeStats(self, player, sort_by='name'):
|
||||||
if gameid > 0 and "0" <= gamenumber[0:1] <= "9":
|
header = self.getStatHeader()
|
||||||
self.gameid = gameid
|
y = 0
|
||||||
self.gamenumber = gamenumber
|
if self._tabs is None:
|
||||||
self.p("%-25s %-20s %17s %s\n" % (gamename, gamenumber, date, status))
|
self._calc_tabs(header)
|
||||||
self.gameid = None
|
self.pstats(y, header)
|
||||||
self.gamenumber = None
|
#
|
||||||
|
y += 2*self.h
|
||||||
|
for result in self.getStatResults(player, sort_by):
|
||||||
|
gameid = result.pop()
|
||||||
|
result[0]=gettext(result[0]) # game name
|
||||||
|
self.pstats(y, result, gameid)
|
||||||
|
y += self.h
|
||||||
|
#
|
||||||
|
y += self.h
|
||||||
|
total, played, won, lost, time, moves, perc = self.getStatSummary()
|
||||||
|
s = _("Total (%d out of %d games)") % (played, total)
|
||||||
|
self.pstats(y, (s, won+lost, won, lost, time, moves, perc))
|
||||||
|
|
||||||
|
def writeLog(self, player, prev_games):
|
||||||
|
y = 0
|
||||||
|
header = self.getLogHeader()
|
||||||
|
t1, t2, t3, t4 = header
|
||||||
|
s = "%-25s %-20s %-17s %s" % header
|
||||||
|
id = self.canvas.create_text(1, y, text=s, anchor="nw",
|
||||||
|
font=self.font, fill=self.fg)
|
||||||
|
self._addItem(id)
|
||||||
|
y += 2*self.h
|
||||||
|
if not player or not prev_games:
|
||||||
|
return 0
|
||||||
|
for result in self.getLogResults(player, prev_games):
|
||||||
|
result[0]=gettext(result[0]) # game name
|
||||||
|
s = "%-25s %-20s %-17s %s" % tuple(result[:4])
|
||||||
|
id = self.canvas.create_text(1, y, text=s, anchor="nw",
|
||||||
|
font=self.font, fill=self.fg)
|
||||||
|
y += self.h
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def writeFullLog(self, player):
|
||||||
|
prev_games = self.app.stats.prev_games.get(player)
|
||||||
|
return self.writeLog(player, prev_games)
|
||||||
|
|
||||||
|
def writeSessionLog(self, player):
|
||||||
|
prev_games = self.app.stats.session_games.get(player)
|
||||||
|
return self.writeLog(player, prev_games)
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
|
@ -617,14 +556,9 @@ class AllGames_StatsDialog(MfxDialog):
|
||||||
def fillCanvas(self, player, header):
|
def fillCanvas(self, player, header):
|
||||||
self.canvas.delete('all')
|
self.canvas.delete('all')
|
||||||
self.nodes = {}
|
self.nodes = {}
|
||||||
a = PysolStatsFormatter(self.app)
|
writer = CanvasFormatter(self.app, self.canvas, self,
|
||||||
#print 'CHAR_W:', self.CHAR_W
|
|
||||||
writer = CanvasWriter(self.canvas, self,
|
|
||||||
self.font, self.CHAR_W, self.CHAR_H)
|
self.font, self.CHAR_W, self.CHAR_H)
|
||||||
if not a.writeStats(writer, player, header, sort_by=self.sort_by):
|
writer.writeStats(player, self.sort_by)
|
||||||
writer.p(_("No entries for player ") + player + "\n")
|
|
||||||
destruct(writer)
|
|
||||||
destruct(a)
|
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
|
@ -636,11 +570,9 @@ class FullLog_StatsDialog(AllGames_StatsDialog):
|
||||||
FONT_TYPE = "fixed"
|
FONT_TYPE = "fixed"
|
||||||
|
|
||||||
def fillCanvas(self, player, header):
|
def fillCanvas(self, player, header):
|
||||||
a = PysolStatsFormatter(self.app)
|
writer = CanvasFormatter(self.app, self.canvas, self,
|
||||||
writer = CanvasWriter(self.canvas, self, self.font, self.CHAR_W, self.CHAR_H)
|
self.font, self.CHAR_W, self.CHAR_H)
|
||||||
if not a.writeFullLog(writer, player, header):
|
writer.writeFullLog(player)
|
||||||
writer.p(_("No log entries for %s\n") % player)
|
|
||||||
destruct(a)
|
|
||||||
|
|
||||||
def initKw(self, kw):
|
def initKw(self, kw):
|
||||||
kw = KwStruct(kw,
|
kw = KwStruct(kw,
|
||||||
|
@ -652,11 +584,10 @@ class FullLog_StatsDialog(AllGames_StatsDialog):
|
||||||
|
|
||||||
class SessionLog_StatsDialog(FullLog_StatsDialog):
|
class SessionLog_StatsDialog(FullLog_StatsDialog):
|
||||||
def fillCanvas(self, player, header):
|
def fillCanvas(self, player, header):
|
||||||
a = PysolStatsFormatter(self.app)
|
a = PysolStatsFormatter()
|
||||||
writer = CanvasWriter(self.canvas, self, self.font, self.CHAR_W, self.CHAR_H)
|
writer = CanvasFormatter(self.app, self.canvas, self,
|
||||||
if not a.writeSessionLog(writer, player, header):
|
self.font, self.CHAR_W, self.CHAR_H)
|
||||||
writer.p(_("No current session log entries for %s\n") % player)
|
writer.writeSessionLog(player)
|
||||||
destruct(a)
|
|
||||||
|
|
||||||
def initKw(self, kw):
|
def initKw(self, kw):
|
||||||
kw = KwStruct(kw,
|
kw = KwStruct(kw,
|
||||||
|
|
Loading…
Add table
Reference in a new issue