1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00

Compare commits

...

8 commits

Author SHA1 Message Date
Shlomi Fish
9af86cddfb Extract a common module/library/header.
This is Refactoring / code cleanup.

See:

* https://refactoring.com/catalog/extractMethod.html

* https://en.wikipedia.org/wiki/Code_refactoring

* https://www.refactoring.com/

* https://www.joelonsoftware.com/2002/01/23/rub-a-dub-dub/

Some small optimisations may have slipped in as well.
2019-04-29 15:14:36 +03:00
Shlomi Fish
90323173a7 Extract a common module/library/header.
This is Refactoring / code cleanup.

See:

* https://refactoring.com/catalog/extractMethod.html

* https://en.wikipedia.org/wiki/Code_refactoring

* https://www.refactoring.com/

* https://www.joelonsoftware.com/2002/01/23/rub-a-dub-dub/

Some small optimisations may have slipped in as well.
2019-04-29 15:08:04 +03:00
Shlomi Fish
9e148b88fe implement the --deal command line param.
It implements a starting deal seed/index/number.
2019-04-29 14:51:01 +03:00
Shlomi Fish
da256a30b0 use normal print to avoid b"...". 2019-04-29 14:25:04 +03:00
Shlomi Fish
cb25f39136 abort on invalid command line game. 2019-04-29 14:24:21 +03:00
Shlomi Fish
4cb94702f3 Add the release process documentation. 2019-04-25 22:22:49 +03:00
Shlomi Fish
436bca2852 Add missing NEWS and AUTHORS to the source dist. 2019-04-25 22:06:16 +03:00
Shlomi Fish
918f177acc prepare for v2.6.4 release. 2019-04-25 21:23:56 +03:00
10 changed files with 189 additions and 114 deletions

View file

@ -33,3 +33,18 @@ Otherwise, the games' sources live under
written in Python 2.7/3.x and you can try inheriting from an existing
variant [class](https://en.wikipedia.org/wiki/Class_%28computer_programming%29).
# The Release Process
In order to publish a new version, follow these steps:
1. Update `NEWS.asciidoc`.
2. Update the `VERSION_TUPLE =` line in `pysollib/settings.py`.
3. Test using `gmake test` .
4. `git commit` the changes .
5. `git tag pysolfc-2.6.5` (or equivalent version).
6. `git push` and `git push --tags` to https://github.com/shlomif/PySolFC .
7. Wait for the AppVeyor build for the tag to complete and scan the .exe using https://www.virustotal.com/ .
8. Run `gmake dist`.
9. Use [rexz9](https://github.com/shlomif/shlomif-computer-settings/blob/567b6ab3f4272ad66bf331536dc80bf58bfff3af/shlomif-settings/bash-aliases/user_aliases.bash#L57) on `dist/PySol*.tar.xz`.
10. Go to https://sourceforge.net/projects/pysolfc/files/PySolFC/ and add a folder called PySolFC-2.6.5 (note the capitalisation).
11. Add the tar.xz and the .exe there and mark them as defaults for the right OSes.

View file

@ -4,7 +4,8 @@
## code
##
include pysol.py setup.py setup_osx.py setup.cfg MANIFEST.in Makefile
include COPYING README.md AUTHORS README.android README.kivy
include COPYING README.md AUTHORS.md README.android README.kivy
include NEWS.asciidoc
#recursive-include pysollib *.py
include pysollib/*.py pysollib/macosx/*.py pysollib/configobj/*.py
include pysollib/winsystems/*.py

View file

@ -1,6 +1,12 @@
[[news]]
=== News
* _25 April, 2019:_ There is a new stable release
https://sourceforge.net/projects/pysolfc/files/PySolFC/PySolFC-2.6.4/[PySolFC
v2.6.4]. New in this release:
** A https://github.com/shlomif/PySolFC/issues/107[new logo] thanks to @ghostofiht.
** Fix for https://github.com/shlomif/PySolFC/issues/110[Freezes] (pygame upgrade)
** Fixed https://github.com/shlomif/PySolFC/issues/111[Three Peaks scoring].
* _7 April, 2019:_ There is a new stable release
https://sourceforge.net/projects/pysolfc/files/PySolFC/PySolFC-2.6.3/[PySolFC
v2.6.3]. New in this release:

View file

@ -25,9 +25,12 @@
# imports
import os
import re
import sys
import traceback
from pickle import UnpicklingError
from pysollib.app_stat import GameStat
from pysollib.app_stat_result import GameStatResult
from pysollib.gamedb import GAME_DB, GI, loadGame
from pysollib.images import Images, SubsampledImages
from pysollib.mfxutil import Struct, destruct
@ -37,7 +40,7 @@ from pysollib.mfxutil import latin1_normalize, print_err
from pysollib.mfxutil import pickle, unpickle
from pysollib.mygettext import _
from pysollib.options import Options
from pysollib.pysolrandom import PysolRandom
from pysollib.pysolrandom import PysolRandom, constructRandom
from pysollib.pysoltk import HTMLViewer
from pysollib.pysoltk import HelpStatusbar, PysolStatusbar
from pysollib.pysoltk import MfxDialog, MfxExceptionDialog, MfxMessageDialog
@ -53,7 +56,7 @@ from pysollib.resource import Sample, SampleManager
from pysollib.resource import Tile, TileManager
from pysollib.settings import DEBUG
from pysollib.settings import PACKAGE, VERSION_TUPLE, WIN_SYSTEM
from pysollib.settings import TOOLKIT, TOP_SIZE
from pysollib.settings import TOOLKIT
from pysollib.util import CARDSET, IMAGE_EXTENSIONS
from pysollib.winsystems import TkSettings
if TOOLKIT == 'tk':
@ -70,112 +73,7 @@ if True: # This prevents from travis 'error' E402.
# ************************************************************************
# * Statistics
# ************************************************************************
class _GameStatResult:
def __init__(self):
self.min = 0
self.max = 0
self.top = []
self.num = 0
self.total = 0 # sum of all values
self.average = 0
def update(self, gameid, value, game_number, game_start_time):
# update min & max
if not self.min or value < self.min:
self.min = value
if not self.max or value > self.max:
self.max = value
# calculate position & update top
position = None
n = 0
for i in self.top:
if value < i.value:
position = n+1
v = Struct(gameid=gameid,
value=value,
game_number=game_number,
game_start_time=game_start_time)
self.top.insert(n, v)
del self.top[TOP_SIZE:]
break
n += 1
if not position and len(self.top) < TOP_SIZE:
v = Struct(gameid=gameid,
value=value,
game_number=game_number,
game_start_time=game_start_time)
self.top.append(v)
position = len(self.top)
# update average
self.total += value
self.num += 1
self.average = float(self.total)/self.num
return position
class GameStat:
def __init__(self, id):
self.gameid = id
#
self.num_total = 0
# self.num_not_won = 0
self.num_lost = 0
self.num_won = 0
self.num_perfect = 0
#
self.time_result = _GameStatResult()
self.moves_result = _GameStatResult()
self.total_moves_result = _GameStatResult()
self.score_result = _GameStatResult()
self.score_casino_result = _GameStatResult()
def update(self, game, status):
#
game_number = game.getGameNumber(format=0)
game_start_time = game.gstats.start_time
# update number of games
# status:
# -1 - NOT WON (not played)
# 0 - LOST
# 1 - WON
# 2 - PERFECT
self.num_total += 1
assert status in (0, 1, 2)
if status == 0:
self.num_lost += 1
return
elif status == 1:
self.num_won += 1
else: # status == 2
self.num_perfect += 1
score = game.getGameScore()
# print 'GameScore:', score
score_p = None
if score is not None:
score_p = self.score_result.update(
game.id, score, game_number, game_start_time)
score = game.getGameScoreCasino()
# print 'GameScoreCasino:', score
score_casino_p = None
if score is not None:
score_casino_p = self.score_casino_result.update(
game.id, score, game_number, game_start_time)
if status == 0:
return
game.updateTime()
time_p = self.time_result.update(
game.id, game.stats.elapsed_time, game_number, game_start_time)
moves_p = self.moves_result.update(
game.id, game.moves.index, game_number, game_start_time)
total_moves_p = self.total_moves_result.update(
game.id, game.stats.total_moves, game_number, game_start_time)
return time_p, moves_p, total_moves_p, score_p, score_casino_p
_GameStatResult = GameStatResult
class Statistics:
@ -418,6 +316,7 @@ class Application:
loadgame=None, # load a game ?
game=None,
gameid=None,
deal=None,
)
self.demo_counter = 0
@ -487,8 +386,12 @@ class Application:
gameid = self.gdb.getGameByName(self.commandline.game)
if gameid is None:
print_err(_("can't find game: ") + self.commandline.game)
sys.exit(-1)
else:
self.nextgame.id, self.nextgame.random = gameid, None
self.nextgame.id = gameid
deal = self.commandline.deal
self.nextgame.random = \
None if deal is None else constructRandom(deal)
elif self.commandline.gameid is not None:
self.nextgame.id, self.nextgame.random = \
self.commandline.gameid, None

82
pysollib/app_stat.py Normal file
View file

@ -0,0 +1,82 @@
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co.
# Copyright (C) 2005-2009 Skomoroh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from pysollib.app_stat_result import GameStatResult
class GameStat:
def __init__(self, id):
self.gameid = id
#
self.num_total = 0
# self.num_not_won = 0
self.num_lost = 0
self.num_won = 0
self.num_perfect = 0
#
self.time_result = GameStatResult()
self.moves_result = GameStatResult()
self.total_moves_result = GameStatResult()
self.score_result = GameStatResult()
self.score_casino_result = GameStatResult()
def update(self, game, status):
#
game_number = game.getGameNumber(format=0)
game_start_time = game.gstats.start_time
# update number of games
# status:
# -1 - NOT WON (not played)
# 0 - LOST
# 1 - WON
# 2 - PERFECT
self.num_total += 1
assert status in (0, 1, 2)
if status == 0:
self.num_lost += 1
return
elif status == 1:
self.num_won += 1
else: # status == 2
self.num_perfect += 1
score = game.getGameScore()
# print 'GameScore:', score
score_p = None
if score is not None:
score_p = self.score_result.update(
game.id, score, game_number, game_start_time)
score = game.getGameScoreCasino()
# print 'GameScoreCasino:', score
score_casino_p = None
if score is not None:
score_casino_p = self.score_casino_result.update(
game.id, score, game_number, game_start_time)
if status == 0:
return
game.updateTime()
time_p = self.time_result.update(
game.id, game.stats.elapsed_time, game_number, game_start_time)
moves_p = self.moves_result.update(
game.id, game.moves.index, game_number, game_start_time)
total_moves_p = self.total_moves_result.update(
game.id, game.stats.total_moves, game_number, game_start_time)
return time_p, moves_p, total_moves_p, score_p, score_casino_p

View file

@ -0,0 +1,62 @@
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co.
# Copyright (C) 2005-2009 Skomoroh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from pysollib.mfxutil import Struct
from pysollib.settings import TOP_SIZE
class GameStatResult:
def __init__(self):
self.min = 0
self.max = 0
self.top = []
self.num = 0
self.total = 0 # sum of all values
self.average = 0
def update(self, gameid, value, game_number, game_start_time):
# update min & max
if not self.min or value < self.min:
self.min = value
if not self.max or value > self.max:
self.max = value
# calculate position & update top
position = None
n = 0
for i in self.top:
if value < i.value:
position = n+1
v = Struct(gameid=gameid,
value=value,
game_number=game_number,
game_start_time=game_start_time)
self.top.insert(n, v)
del self.top[TOP_SIZE:]
break
n += 1
if not position and len(self.top) < TOP_SIZE:
v = Struct(gameid=gameid,
value=value,
game_number=game_number,
game_start_time=game_start_time)
self.top.append(v)
position = len(self.top)
# update average
self.total += value
self.num += 1
self.average = float(self.total)/self.num
return position

View file

@ -86,7 +86,7 @@ def parse_option(argv):
prog_name = argv[0]
try:
optlist, args = getopt.getopt(argv[1:], "g:i:hD:",
["game=", "gameid=",
["deal=", "game=", "gameid=",
"french-only",
"noplugins",
"nosound",
@ -97,6 +97,7 @@ def parse_option(argv):
(err, prog_name), 0)
return None
opts = {"help": False,
"deal": None,
"game": None,
"gameid": None,
"french-only": False,
@ -107,6 +108,8 @@ def parse_option(argv):
for i in optlist:
if i[0] in ("-h", "--help"):
opts["help"] = True
elif i[0] in ("--deal"):
opts["deal"] = i[1]
elif i[0] in ("-g", "--game"):
opts["game"] = i[1]
elif i[0] in ("-i", "--gameid"):
@ -164,6 +167,7 @@ def pysol_init(app, args):
opts, filename = opts
if filename:
app.commandline.loadgame = filename
app.commandline.deal = opts['deal']
app.commandline.game = opts['game']
if opts['gameid'] is not None:
try:

View file

@ -107,9 +107,9 @@ def print_err(s, level=1):
elif level == 2:
ss = PACKAGE+': DEBUG WARNING:'
try:
print_(ss, s.encode(locale.getpreferredencoding()), file=sys.stderr)
except Exception:
print_(ss, s, file=sys.stderr)
except Exception:
print_(ss, s.encode(locale.getpreferredencoding()), file=sys.stderr)
sys.stderr.flush()

View file

@ -32,7 +32,7 @@ PACKAGE = 'PySolFC'
TITLE = 'PySol'
PACKAGE_URL = 'http://pysolfc.sourceforge.net/'
VERSION_TUPLE = (2, 6, 3)
VERSION_TUPLE = (2, 6, 4)
VERSION = '.'.join(map(str, VERSION_TUPLE))
# Tk windowing system (auto set up in init.py)

View file

@ -14,6 +14,8 @@ for module_name in \
'pysollib.acard',
'pysollib.actions',
'pysollib.app',
'pysollib.app_stat',
'pysollib.app_stat_result',
'pysollib.configobj.configobj',
'pysollib.configobj.validate',
'pysollib.customgame',