Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.pydevproject10
-rw-r--r--docs/Readme.txt12
-rw-r--r--docs/Sample Lesson Plan.odtbin0 -> 24575 bytes
-rw-r--r--docs/diagrams/TextMenus.diabin5147 -> 5110 bytes
-rw-r--r--docs/examples/config.xml19
-rw-r--r--docs/examples/lvl-1.mlvl8
-rw-r--r--docs/examples/profile.mpro (renamed from docs/examples/profile.xml)0
-rw-r--r--docs/examples/readme.txt2
-rw-r--r--docs/web/SugarLab ProjectWiki Page.txt64
-rw-r--r--src/game/__init__.py0
-rw-r--r--src/game/start.py25
-rw-r--r--src/setup/config.py148
-rw-r--r--src/setup/menus.py300
-rw-r--r--src/setup/profile.py69
-rw-r--r--src/setup/profiles.py34
-rw-r--r--src/utils/__init__.py1
-rw-r--r--src/utils/strs.py35
17 files changed, 647 insertions, 80 deletions
diff --git a/.pydevproject b/.pydevproject
deleted file mode 100644
index eb7c2c2..0000000
--- a/.pydevproject
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?eclipse-pydev version="1.0"?>
-
-<pydev_project>
-<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
-<path>/Muthris/src</path>
-</pydev_pathproperty>
-<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 3.0</pydev_property>
-<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">/usr/bin/python3</pydev_property>
-</pydev_project>
diff --git a/docs/Readme.txt b/docs/Readme.txt
new file mode 100644
index 0000000..0e19eee
--- /dev/null
+++ b/docs/Readme.txt
@@ -0,0 +1,12 @@
+Muthris
+
+Required Software
+* Python 2.6
+* lxml for Python XML processing (for Ubuntu: sudo apt-get install python-lxml)
+
+Running Muthris
+0) Install the required software (see above)
+1) Download the complete source code
+2) Optional: Edit 'LoggingFile' in 'Muthris/src/utils/strs.py' to change the destination of the debug output
+3) Change the working directory to Muthris' folder
+4) Run: python ./src/setup/main.py
diff --git a/docs/Sample Lesson Plan.odt b/docs/Sample Lesson Plan.odt
new file mode 100644
index 0000000..bb61597
--- /dev/null
+++ b/docs/Sample Lesson Plan.odt
Binary files differ
diff --git a/docs/diagrams/TextMenus.dia b/docs/diagrams/TextMenus.dia
index b08cd5d..81d5181 100644
--- a/docs/diagrams/TextMenus.dia
+++ b/docs/diagrams/TextMenus.dia
Binary files differ
diff --git a/docs/examples/config.xml b/docs/examples/config.xml
index 7198e37..f2b8a12 100644
--- a/docs/examples/config.xml
+++ b/docs/examples/config.xml
@@ -3,12 +3,27 @@
<config>
<!-- Contains a listing of all the folders that should be scanned for levels (.mlvl files) -->
<level-folders>
- <folder location='/home/doug/workspace/Muthris/docs/examples'/>
+ <folder location='./docs/examples'/>
</level-folders>
<!-- -->
- <settings>
+ <profile-folders>
+ <folder location='./docs/examples'/>
+ </profile-folders>
+
+ <!-- Things that were last used/inputed -->
+ <last>
+ <profile name='dpk3062'/>
+ </last>
+ <!-- -->
+ <settings>
+ <!--
+ model-store
+ * "enabled='true'" for storing a copy of the model on this client and validating all use input before sending to the server
+ * "enabled='false'" for not storing a model copy in-order to save memory, but at the cost of sending every use command to the server
+ -->
+ <model-store enabled='true'/>
</settings>
</config>
</muthris>
diff --git a/docs/examples/lvl-1.mlvl b/docs/examples/lvl-1.mlvl
index 755d600..f0788f6 100644
--- a/docs/examples/lvl-1.mlvl
+++ b/docs/examples/lvl-1.mlvl
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<muthris>
- <level-info name='Demo Level 1' description='The first demo level' version='1'>
+ <level name='Demo Level 1' description='The first demo level' version='1'>
<!-- TODO Need to figure out how localization fits in with all the raw text -->
@@ -45,12 +45,14 @@
<action name='Score' script='../game/sys-actions/Scores.py' description="Occurs when a player's score changes"/>
<action name='GroupFound' script='../game/sys-actions/GroupFound.py' description='Occurs when a block grouping is found'/>
<action name='PlayerGroupStopped' script='../game/sys-actions/PGS.py' description='Occurs when the blocks the player controls have fallen onto other blocks'/>
+ <!--
<action name='' script='' description=''/>
<action name='' script='' description=''/>
+ -->
</system>
<!--
- There are certain actions the system looks for. It uses the names to id the actions it needs to use. If a required system action is missing, then that action cannot happen. A factory class is used to generate the actions from their names.
+ There are certain actions the system looks for. It uses the names to id the actions it needs to use. If a required system action is missing, then that action cannot happen. A factory class is used to generate the actions from their names.
-->
</actions>
@@ -81,6 +83,6 @@
<block script='dl1/PrimeBlock.py'/>
</blocks>
- </level-info>
+ </level>
</muthris>
diff --git a/docs/examples/profile.xml b/docs/examples/profile.mpro
index 053c75e..053c75e 100644
--- a/docs/examples/profile.xml
+++ b/docs/examples/profile.mpro
diff --git a/docs/examples/readme.txt b/docs/examples/readme.txt
index 7bef7fa..b7da0f1 100644
--- a/docs/examples/readme.txt
+++ b/docs/examples/readme.txt
@@ -1,5 +1,5 @@
The Examples folder contains:
* config.xml - An example Muthris configuration file
* lvl-1.mlvl - An example level descriptor file
-* profile.xml - An example player profile file
+* profile.mpro - An example player profile file
diff --git a/docs/web/SugarLab ProjectWiki Page.txt b/docs/web/SugarLab ProjectWiki Page.txt
deleted file mode 100644
index faa200c..0000000
--- a/docs/web/SugarLab ProjectWiki Page.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-=Muthris=
-Muthris is a math themed, Tetris-based game inspired by Cuyo. Players control falling blocks which must be grouped in certain ways in-order to clear that grouping from the board. For more details, see the project's Vision and Scope document contained in its Sugar Labs' Gitorious repository (once the repository is working...).
-==Updates as of April 29th, 2009==
-* Updated Wiki page
-* Falling back to a local Git repository to prevent further delays
-* Working on flow charts
-* Working on file formats
-==Developers==
-*[[User:Dpk3062|Douglas Krofcheck]]
-==Goals==
-* To be fun to play
-* To teach mathematical concepts
-* To be discrete in its teachings
-* To follow good software engineering practices during development
-==Schedule and Tasks==
-* By May 1st, 2009
-** Have completed most important flow charts
-** Developers completed the Python tutorials
-* By May 8th, 2009
-** Have completed architecture documentation
-** Developers completed the PyGame tutorials
-* By May 15th, 2009
-** Determine test plans
-** Review design documents
-** Start coding of system skeleton
-* By May 22nd, 2009
-** Determine future development plans
-==Overall Plan==
-===Must Have===
-* Project Documentation
-** Vision and Scope
-** Architecture docs
-** Flow Charts
-* Working code repository
-* Project schedule
-* At least one developer
-* Text-based version of the game
-* Readme
-===Should Have===
-* Skeleton - working, stubbed framework before general coding
-* Installation tutorial
-* Program walk-through
-* GUI version of the game
-* Build tutorial
-* Project backup
-===Nice to Have===
-* Unit tests
-* SRS Document
-* Release 1
-* No major project risks
-==Major Project Risks==
-* Git repository not currently working for any developers
-* Developers do not know Python or PyGame well
-* Developmental time constraints
-* Short overall time frame
-==Other Info==
-===Potential Contacts===
-*[[User:Dpk3062|Douglas Krofcheck]]
-===Links and Resources===
-*[http://git.sugarlabs.org/projects/muthris Project Repository] - (committing not yet working)
-*[http://www.openoffice.org/ OpenOffice.org] - to read documentation files (.odt)
-*[http://live.gnome.org/Dia Dia] - To view flow charts (.dia)
-===Initial Math4OLPC Educational Target===
-* 4.N.7 - Recognize classes (in particular, odds, evens; factors or multiples of a given number; and squares) to which a number may belong, and identify the numbers in those classes. Use these in the solution of problems
diff --git a/src/game/__init__.py b/src/game/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/game/__init__.py
diff --git a/src/game/start.py b/src/game/start.py
new file mode 100644
index 0000000..7b0b3f2
--- /dev/null
+++ b/src/game/start.py
@@ -0,0 +1,25 @@
+'''
+
+'''
+
+import curses
+import config
+from utils import strs
+
+# setup logging
+import logging
+logging.basicConfig(filename=strs.LoggingFile,level=logging.DEBUG)
+log = logging.getLogger('game.start')
+
+
+
+
+def startGame(data):
+ '''Called to start the level. The given data is the same data structure used by the menu system'''
+ #TODO Load the level scripts
+ #TODO Start the server
+ #TODO Start the client
+ #TODO Connect the client to the server
+ print('Wasn\'t that fun?') #TODO remove this line
+ pass
+
diff --git a/src/setup/config.py b/src/setup/config.py
new file mode 100644
index 0000000..c844781
--- /dev/null
+++ b/src/setup/config.py
@@ -0,0 +1,148 @@
+'''
+
+'''
+
+import os
+from lxml import etree # using lxml for XML processing
+from utils import strs # string constants
+from utils import utils # some XML utilities
+from profile import Profile
+from level import Level
+
+# setup logging
+import logging
+logging.basicConfig(filename=strs.LoggingFile,level=logging.DEBUG)
+log = logging.getLogger('setup.config')
+
+
+# -----------------------------------------------------------------------------
+# Some Getters
+# -----------------------------------------------------------------------------
+
+# TODO refactor to remove duplicated code logic: should have the two getXXX() going to findFiles() -> findFolders() -> find()
+
+def getLevelDescriptors():
+ '''Returns a list of Levels representing all known levels'''
+ # get all the level descriptor files
+ files = findLevelFiles()
+
+ # convert them all into objects
+ levels = []
+ for file in files:
+ level = Level(file)
+ levels.append(level)
+ return levels
+
+def getProfiles():
+ '''Returns a list of Profiles representing all known profiles'''
+ # get all the profile files
+ files = findProfileFiles()
+
+ # convert the files into Profile objects
+ profiles = []
+ for file in files:
+ profile = Profile(path=file)
+ profiles.append(profile)
+ return profiles
+
+def getProfile(name):
+ '''Returns the player profile with the given name. If such a profile doesn't exist, one is created'''
+
+ # search through the know profiles for the one with the given name
+ profiles = getProfiles()
+ for profile in profiles:
+ log.debug('Looking for a profile named: ' + name + ' and found: ' + profile.getName())
+ if profile.getName() == name:
+ return profile
+
+ # the wanted profile doesn't exist, so create a new one
+ return createProfile(name)
+
+# -----------------------------------------------------------------------------
+# File related methods
+# -----------------------------------------------------------------------------
+
+def getLastProfileName():
+ '''Returns the name of the last loaded profile'''
+ name = find(strs.XP_LastProfileName)[0]
+ return name
+
+def findLevelFiles():
+ '''Returns the list of found level descriptor files'''
+ folders = findLevelFolders()
+ files = findFiles(folders, strs.Ext_Level)
+ log.debug('Found ' + str(len(files)) + ' level files')
+ return files
+
+def findProfileFiles():
+ '''Returns the list of found profile files'''
+ folders = findProfileFolders()
+ files = findFiles(folders, strs.Ext_Profile)
+ log.debug('Found ' + str(len(files)) + ' profile files')
+ return files
+
+def findFiles(folders, extension):
+ '''Returns a list of all files with the given extension directly inside the given folders'''
+ files = []
+
+ #for each given folder,
+ for dir in folders:
+ contents = os.listdir(dir)
+
+ #for each directory in the folder,
+ for item in contents:
+ item = dir + '/' + item # must convert the file/folder name into its complete path
+
+ # only want files with the given extension
+ if not os.path.isfile(item):
+ continue
+ if not item.endswith(extension):
+ continue
+
+ files.append(item)
+ return files
+
+# -----------------------------------------------------------------------------
+#
+# -----------------------------------------------------------------------------
+
+def createProfile(profileName):
+ '''Creates and returns a new profile with the given profileName. This profile has not yet been saved to the disk'''
+
+ log.debug('Creating a Profile with the name: ' + profileName)
+ return Profile(name=profileName)
+
+# -----------------------------------------------------------------------------
+# Folder related methods
+# -----------------------------------------------------------------------------
+
+def findLevelFolders():
+ '''Returns the list of known level folders'''
+ folders = find(strs.XP_LevelFolderLocation)
+ log.debug('Found ' + str(len(folders)) + ' level folders')
+ return folders
+ pass
+
+def findProfileFolders():
+ '''Returns the list of known profile folders'''
+ folders = find(strs.XP_ProfileFolderLocation)
+ log.debug('Found ' + str(len(folders)) + ' profile folders')
+ return folders
+
+# -----------------------------------------------------------------------------
+# General methods
+# -----------------------------------------------------------------------------
+
+def find(xpath):
+ '''Returns the result of applying the given xpath onto the config file'''
+ config = utils.getXMLRoot(strs.ConfigFile)
+ return config.xpath(xpath)
+
+# -----------------------------------------------------------------------------
+# Some Setters
+# -----------------------------------------------------------------------------
+
+def setLastProfileName(name):
+ '''Stores the name of the last used profile. This is so on next startup, the last used profile can start as the default player'''
+ # TODO fill in this stub
+ pass
diff --git a/src/setup/menus.py b/src/setup/menus.py
new file mode 100644
index 0000000..471b545
--- /dev/null
+++ b/src/setup/menus.py
@@ -0,0 +1,300 @@
+'''
+
+'''
+
+import curses
+import config
+from utils import strs
+from game import start
+
+# setup logging
+import logging
+logging.basicConfig(filename=strs.LoggingFile,level=logging.DEBUG)
+log = logging.getLogger('setup.menus')
+
+# -----------------------------------------------------------------------------
+#
+# -----------------------------------------------------------------------------
+
+class MenuData(object):
+ '''Holds data used by the menu system'''
+
+ def __init__(self):
+ '''
+ Constructor
+ '''
+ self.levels = [] # all the known levels
+ self.profiles = [] # all the known profiles
+ self.profile = None # the player's current profile
+ self.screen = None # the curses display
+ self.level = None # the level the player wants to play
+
+
+# -----------------------------------------------------------------------------
+# Menu display functions
+# -----------------------------------------------------------------------------
+
+# Warning: the menu system uses recursion to move about. Excessive bad input (tested to crash at 979 bad inputs to the main menu) or moving between menus will case a stack overflow. When the menu system exits (such as when actually playing a game), we need to make sure all of the menu's function calls unwind
+# TODO: improve the menu system so it doesn't use recursion
+
+def mainMenu(data):
+ '''Displays the 'Main Menu' and handles its input'''
+
+ # we use the current profile, so make sure there is one
+ if (data.profile == None) | (data.profile == ''):
+ changePlayerMenu(data)
+ return
+
+ # configure the screen for our needs
+ data.screen.erase()
+ curses.cbreak()
+ curses.echo()
+
+ # display the title
+ title = strs.Title_Main + strs.Title_Seperator + (data.profile or '[No Player]')
+ displayTitle(data.screen, title)
+
+ # display the menu options
+ lines = ('1) Play Game',
+ '2) Join Game - Stubbed',
+ '3) Options - Stubbed',
+ '',
+ 'c) Change Player',
+ 'e) Exit')
+ displayOptions(data.screen, lines, 1)
+
+ # display the input prompt
+ lines = ('', 'Pick [1,c,e]: ')
+ displayPrompt(data.screen, lines, 7)
+
+ # refresh the screen
+ data.screen.refresh()
+
+ ## No longer matters as we are redrawing the entire screen after every key press
+ # store the current cursor location, so we can keep it here when the user types
+ #y, x = data.screen.getyx()
+ #log.debug('Y,X are at: ' + str(y) + ' ' + str(x))
+
+ # wait for user input
+ c = data.screen.getch()
+
+ ## No longer matters as we are redrawing the entire screen after every key press
+ # keep the cursor in the same spot
+ #data.screen.move(y, x)
+
+ # process input
+ if c == ord('1'): playGameMenu(data)
+ #elif c == ord('2'): curses.beep()
+ #elif c == ord('3'): curses.beep()
+ elif c == ord('c'): changePlayerMenu(data)
+ elif c == ord('e'): pass
+ else:
+ mainMenu(data)
+
+def changePlayerMenu(data):
+ '''Displays the 'Change Player Profile' menu and handles its input'''
+
+ # create a list of players
+ profiles = config.getProfiles()
+ players = []
+ for profile in profiles:
+ players.append(profile.getName())
+
+ # configure the screen for our needs
+ data.screen.erase()
+ curses.nocbreak()
+ curses.echo()
+
+ # display the title
+ title = strs.Title_ChangePlayer + strs.Title_Seperator + (data.profile or '[No Player]')
+ displayTitle(data.screen, title)
+
+ # display the menu options
+ lines = ['', 'Known Players:']
+ for player in players:
+ lines.append(' * ' + player)
+ displayOptions(data.screen, lines, 1)
+
+ # display the input prompt
+ offset = len(lines) + 1
+ lines = ('','Enter your player\'s name: ')
+ displayPrompt(data.screen, lines, offset)
+
+ # refresh and wait for valid user input
+ data.screen.refresh()
+ name = data.screen.getstr()
+
+ # process input
+ # Note: if the player's profile doesn't exist, it will be created whenever the player does something that needs to be saved to a profile
+ data.profile = name
+
+ # always head back to the main menu after changing the profile
+ mainMenu(data)
+
+def playGameMenu(data):
+ '''Displays the 'Play Game' menu and handles its input'''
+
+ # create a list of levels
+ if (data.levels == None) | (data.levels == []):
+ data.levels = config.getLevelDescriptors()
+
+ # configure the screen for our needs
+ data.screen.erase()
+ curses.cbreak()
+ curses.echo()
+
+ # display the title
+ title = strs.Title_PlayGame + strs.Title_Seperator + (data.profile or '[No Player]')
+ displayTitle(data.screen, title)
+
+ # display the menu options
+ lines = ['', 'Levels:']
+ for index, level in enumerate(data.levels):
+ lines.append(' ' + str(index) + ') ' + level.getName() )
+ displayOptions(data.screen, lines, 1)
+
+ # display the input prompt
+ minLevels = 1
+ offset = len(lines) + 1
+ if len(data.levels) < minLevels:
+ lines = ('', 'No known levels. Press anything to continue...'),
+ curses.nocbreak()
+ else:
+ lines = ('','Enter the number of the level to play: ')
+ displayPrompt(data.screen, lines, offset)
+
+ # refresh and wait for valid user input
+ data.screen.refresh()
+ input = data.screen.getstr()
+
+ # process input
+ if len(data.levels) < minLevels:
+ mainMenu(data)
+ return
+ input = int(input)
+ data.level = data.levels[input]
+
+ #move on to configuring the selected level
+ levelOptionsMenu(data)
+
+def levelOptionsMenu(data):
+ '''Displays the level options menu and handles its input'''
+
+ # make sure there is a level
+ if (data.level == None) | (data.level == ''):
+ log.error('Made it to the levelOptionsMenu() without a selected level! This should not be possible.')
+ return
+
+ # get the player's stats for this level
+ stats = []
+ if data.profile == None:
+ pass
+ else:
+ stats.append('')
+ stats.append('Your Stats:')
+
+ # get the max score, max duration, and last time played
+ profile = config.getProfile(data.profile)
+ stats.append('Max Score - ' + str(profile.getMaxScore(data.level)))
+ stats.append('Max Duration - ' + str(profile.getMaxDuration(data.level)))
+ stats.append('Last Played - ' + str(profile.getLastTimePlayed(data.level)))
+ stats.append('')
+
+ # configure the screen for our needs
+ data.screen.erase()
+ curses.cbreak()
+ curses.echo()
+
+ # display the title
+ title = data.level.getName() + strs.Title_Seperator + (data.profile or '[No Player]')
+ displayTitle(data.screen, title)
+
+ # display the level's description, the player's stats, and the level's options
+ lines = ['', data.level.getDescription()]
+ lines.extend(stats)
+ lines.append('-------------------- -------------------- --------------------')
+ lines.extend(['','Options:',
+ '1) Skill level - Easy - Stubbed',
+ '2) Number of players - 1 - Stubbed',
+ '',
+ 'p) Play now',
+ 's) Spectate - Stubbed',
+ 'm) Main Menu'])
+ displayOptions(data.screen, lines, 1)
+ #displayOptions(data.screen, ['Nothing'], 1)
+
+ # display the input prompt
+ offset = len(lines) + 1
+ lines = ('','Pick [p,m]: ')
+ displayPrompt(data.screen, lines, offset)
+
+ # refresh and wait for valid user input
+ data.screen.refresh()
+ c = data.screen.getch()
+
+ # process input
+ if c == ord('p'): start.startGame(data) # TODO remove the recursiveness of the menu system
+ elif c == ord('m'): mainMenu(data)
+ else:
+ levelOptionsMenu(data)
+
+def skillLevelMenu(data):
+ '''Displays the 'Skill Level' menu and handles its input'''
+ # TODO:
+ # check for required vars
+ # clear the screen and display the title
+ # display the menu
+ # refresh the screen
+ # wait for input
+ # process input
+ pass
+
+def numberOfPlayersMenu(data):
+ '''Displays the 'Number of Players' menu and handles its input'''
+ # TODO:
+ # check for required vars
+ # clear the screen and display the title
+ # display the menu
+ # refresh the screen
+ # wait for input
+ # process input
+ pass
+
+# -----------------------------------------------------------------------------
+# Common functions
+# -----------------------------------------------------------------------------
+
+def displayTitle(screen, title):
+ '''Displays the given title as the title of the given stdscr'''
+ screen.addstr(0,strs.Indent_Title, title, curses.A_REVERSE)
+
+def displayOptions(screen, options, offset=0):
+ '''Displays the given list of options on the given stdscr with the given vertical offset'''
+ for index, line in enumerate(options):
+ screen.addstr(index+1+offset,strs.Indent_Options, line)
+
+def displayPrompt(screen, lines, offset=0):
+ '''Displays the given list of textual prompt lines on the given stdscr with the given vertical offset'''
+ for index, line in enumerate(lines):
+ screen.addstr(index+1+offset,strs.Indent_Prompt, line)
+
+# -----------------------------------------------------------------------------
+# Menu setup functions
+# -----------------------------------------------------------------------------
+
+def init(stdscr):
+ '''Enters the menu system'''
+
+ # create the menu's data
+ data = MenuData()
+ data.screen = stdscr
+
+ # set the last used values
+ data.profile = config.getLastProfileName()
+
+ mainMenu(data)
+
+def begin():
+ '''Configures Curses'''
+ curses.wrapper(init)
+
diff --git a/src/setup/profile.py b/src/setup/profile.py
new file mode 100644
index 0000000..96b4caf
--- /dev/null
+++ b/src/setup/profile.py
@@ -0,0 +1,69 @@
+'''
+
+'''
+
+from lxml import etree # using lxml for XML processing
+from utils import strs # string constants
+from utils import utils # some XML utilities
+
+# setup logging
+import logging
+logging.basicConfig(filename=strs.LoggingFile,level=logging.DEBUG)
+log = logging.getLogger('setup.profile')
+
+class Profile(object):
+ '''
+ '''
+
+ def __init__(self, path=None, name=None ):
+ '''
+ Constructor
+ '''
+
+ # new profiles have a name instead of a path
+ if path != None:
+ #open up the mpro file and read in its basic properties
+ root = utils.getXMLRoot(path)
+ self.name = root.xpath(strs.XP_ProfileName)[0]
+ self.path = path
+ else:
+ # there is no XML representation of this Profile, so just store its name
+ self.name = name
+ self.path = None
+ pass
+
+ def getName(self):
+ '''Returns the name of the profile's user'''
+ return self.name
+
+ def getMaxScore(self, level=None, skill=None):
+ '''Returns the player's max score corresponding to the given filters'''
+
+ # if no path, then no XML to read for the max score
+ if self.path == None:
+ return 0
+
+ # TODO read in/calculate the max score of this player. Need to take into account the level and skill parameters
+ log.debug('getMaxScore() is stubbed to return 1')
+ return 1
+
+ def getMaxDuration(self, level=None, skill=None):
+ '''Returns the player's max playing duration corresponding to the given filters'''
+
+ # if no path, then no XML to read for the max duration
+ if self.path == None:
+ return 0
+
+ # TODO read in/calculate the max duration of this player. Need to take into account the level and skill parameters
+ log.debug('getMaxDuration() is stubbed to return 1')
+ return 1
+
+ def getLastTimePlayed(self, level=None, skill=None):
+ '''Returns the player's max last time played corresponding to the given filters'''
+ # if no path, then no XML to read for the last time played
+ if self.path == None:
+ return 0
+
+ # TODO read in/calculate the last time played for this player. Need to take into account the level and skill parameters
+ log.debug('getLastTimePlayed() is stubbed to return "06-21-2009.12:59"')
+ return '06-21-2009.12:59'
diff --git a/src/setup/profiles.py b/src/setup/profiles.py
new file mode 100644
index 0000000..6320e01
--- /dev/null
+++ b/src/setup/profiles.py
@@ -0,0 +1,34 @@
+'''
+I don't think this class is used any more as its functions have been moved into config.py
+'''
+
+import os # file path support
+from lxml import etree # using lxml for XML processing
+from utils import utils # some XML utilities
+from utils import strs # string constants
+
+# setup logging
+import logging # logging support
+logging.basicConfig(level=logging.DEBUG)
+log = logging.getLogger('setup.profiles')
+
+
+
+def findAllProfiles():
+ '''Returns a listing of all profiles'''
+ #TODO
+ pass
+
+def getLastUsedProfile():
+ '''Returns the last used player profile'''
+ #TODO
+ pass
+
+def createNewProfile():
+ '''Creates a new player profile'''
+ #TODO
+ pass
+
+
+
+
diff --git a/src/utils/__init__.py b/src/utils/__init__.py
index e69de29..a003759 100644
--- a/src/utils/__init__.py
+++ b/src/utils/__init__.py
@@ -0,0 +1 @@
+# this is a package
diff --git a/src/utils/strs.py b/src/utils/strs.py
new file mode 100644
index 0000000..2a25db3
--- /dev/null
+++ b/src/utils/strs.py
@@ -0,0 +1,35 @@
+'''
+Created on Jul 5, 2009
+
+@author: doug
+'''
+
+# files and folders
+ConfigFile = './docs/examples/config.xml'
+LoggingFile = '/tmp/muthris-dev.log' #TODO move this into the ConfigFile?
+
+# file extensions
+Ext_Level = '.mlvl'
+Ext_Profile = '.mpro'
+
+# XML locations (XPaths)
+XP_LevelFolderLocation = '/muthris/config/level-folders/folder/@location'
+XP_ProfileFolderLocation = '/muthris/config/profile-folders/folder/@location'
+XP_LastProfileName = '/muthris/config/last/profile/@name'
+XP_LevelName = '/muthris/level/@name'
+XP_LevelDescription = '/muthris/level/@description'
+XP_ProfileName = '/muthris/profile/@name'
+
+# menu titles
+Title_Main = 'Main Menu'
+Title_ChangePlayer = 'Change Player'
+Title_PlayGame = 'Play Game'
+# Title_LevelOptions = '' # title uses the name of the level
+Title_SkillLevel = 'Skill Level'
+Title_NumberOfPlayers = 'Number of Players'
+Title_Seperator = ' - '
+
+# indent spacing for curses
+Indent_Title = 25
+Indent_Options = 10
+Indent_Prompt = 5 \ No newline at end of file