[Tux4kids-commits] r343 - in tuxmath/trunk: doc src
tholy-guest at alioth.debian.org
tholy-guest at alioth.debian.org
Mon Nov 26 06:29:31 UTC 2007
Author: tholy-guest
Date: 2007-11-26 06:29:31 +0000 (Mon, 26 Nov 2007)
New Revision: 343
Modified:
tuxmath/trunk/doc/README.txt
tuxmath/trunk/doc/TODO.txt
tuxmath/trunk/doc/changelog
tuxmath/trunk/src/fileops.c
tuxmath/trunk/src/setup.c
tuxmath/trunk/src/setup.h
tuxmath/trunk/src/titlescreen.c
Log:
Add the possibility of a user login at the beginning of the game.
Modified: tuxmath/trunk/doc/README.txt
===================================================================
--- tuxmath/trunk/doc/README.txt 2007-11-23 11:02:43 UTC (rev 342)
+++ tuxmath/trunk/doc/README.txt 2007-11-26 06:29:31 UTC (rev 343)
@@ -23,7 +23,13 @@
please read the "INSTALL.txt" file.
+Configuration
+-------------
+ School-type settings in which all students have a single username
+ may benefit from additional configuration---see below under
+ "Configuring multiple users."
+
Running The Program
-------------------
Linux/Unix
@@ -353,7 +359,52 @@
[ UNDER CONSTRUCTION ]
+Configuring Multiple Users
+--------------------------
+ In some cases, the user's log-in name is not very informative: an
+ example is when schools use a single username "student" for all
+ students in the school. It is possible to set up Tuxmath so that it
+ asks students to "log in" (without any password) when they first
+ start the game. This will insure that all gold stars, options, and
+ game summary files will be stored in a location specific to each
+ user.
+
+ Setting this up is fairly simple:
+
+ 1. Decide where you want this information stored. You might want
+ to put it on a central server. In the appropriate place
+ (let's say it's "/servervolume/"), create a directory which
+ we'll call "tuxmath_users" for current purposes.
+
+ 2. Create subdirectories of "tuxmath_users." The basic idea is
+ that you'll create a directory tree that mirrors how you want
+ students to select themselves. For example, a large school
+ with many classrooms might create directories called
+ "Kindergarten," "1st grade," and so on. Then inside
+ "Kindergarten" you might want to create directories for each
+ classroom, say "Mrs. Smith" and "Mr. Jones." A smaller school
+ might choose to skip the by-grade organization and go straight
+ to each classroom; a single computer in a single classroom
+ might skip these altogether.
+
+ 3. At the finest level, create one subdirectory for each student.
+
+ 4. Finally, adjust the launch command for tuxmath to pass the
+ command line option "--homedir /severvolume/tuxmath_users"
+ (along with any other options) upon launching tuxmath. Note
+ that an individual classroom could make use of this
+ school-wide service by specifying "--homedir
+ /servervolume/tuxmath_users/2nd\ grade/Mrs.\ Johnson" so that
+ students in a particular classroom only have to choose among
+ their own class.
+
+ You have to make sure that all the write permissions are set
+ correctly.
+
+ Note there is no security insuring that students select themselves.
+
+
License
-------
"Tux, of Math Command" is Free Software, distributable under the
Modified: tuxmath/trunk/doc/TODO.txt
===================================================================
--- tuxmath/trunk/doc/TODO.txt 2007-11-23 11:02:43 UTC (rev 342)
+++ tuxmath/trunk/doc/TODO.txt 2007-11-26 06:29:31 UTC (rev 343)
@@ -44,6 +44,8 @@
* Admin options screen / files
* Command-line options based on grade-level (?)
* Internationalization - use gettext() for all strings
+ * Install some kind of security on --homedir, to make sure that
+ tuxmath can write but that students can't edit the files by hand?
Code:
* Optimize graphics blitting!!!
Modified: tuxmath/trunk/doc/changelog
===================================================================
--- tuxmath/trunk/doc/changelog 2007-11-23 11:02:43 UTC (rev 342)
+++ tuxmath/trunk/doc/changelog 2007-11-26 06:29:31 UTC (rev 343)
@@ -1,3 +1,9 @@
+2007.Nov.26 (svn.debian.org/tux4kids - revision 342)
+ Options:
+ * Added support for user login. This should be helpful in school
+ settings where all students log in with the same username. See
+ the README for details.
+
2007.Nov.18 (svn.debian.org/tux4kids - revision 327)
Build:
Modified: tuxmath/trunk/src/fileops.c
===================================================================
--- tuxmath/trunk/src/fileops.c 2007-11-23 11:02:43 UTC (rev 342)
+++ tuxmath/trunk/src/fileops.c 2007-11-26 06:29:31 UTC (rev 343)
@@ -410,6 +410,7 @@
/* This functions keep and returns the user data directory application path */
static char* user_data_dir = NULL;
+static int add_subdir = 1;
char *get_user_data_dir ()
{
@@ -423,6 +424,36 @@
return user_data_dir;
}
+/* This function sets the user data directory, and also sets a flag
+ indicating that this should function as a .tuxmath directory, and
+ thus doesn't need the subdir appended. */
+void set_user_data_dir(const char *dirname)
+{
+ int len;
+
+ if (user_data_dir != NULL)
+ free(user_data_dir); // clear the previous setting
+
+ user_data_dir = strdup(dirname);
+
+ // Check to see that dirname is properly terminated
+ len = strlen(user_data_dir);
+ if (user_data_dir[len-1] != '/')
+ strcat(user_data_dir,"/");
+
+ // If the user supplies a homedir, interpret it literally and don't
+ // add .tuxmath
+ add_subdir = 0;
+}
+
+/* This gets the user data directory including the .tuxmath, if applicable */
+void get_user_data_dir_with_subdir(char *opt_path)
+{
+ strcpy(opt_path, get_user_data_dir());
+ if (add_subdir)
+ strcat(opt_path, OPTIONS_SUBDIR "/");
+}
+
/* FIXME should have better file path (/etc or /usr/local/etc) and name */
int read_global_config_file(void)
{
@@ -447,8 +478,8 @@
char opt_path[PATH_MAX];
/* find $HOME and tack on file name: */
- strcpy(opt_path, get_user_data_dir());
- strcat(opt_path, OPTIONS_SUBDIR "/" OPTIONS_FILENAME);
+ get_user_data_dir_with_subdir(opt_path);
+ strcat(opt_path, OPTIONS_FILENAME);
#ifdef TUXMATH_DEBUG
printf("\nIn read_user_config_file() full path to config file is: = %s\n", opt_path);
@@ -650,8 +681,7 @@
/* Look in user's hidden .tuxmath directory */
/* find $HOME and tack on file name: */
- strcpy(opt_path, get_user_data_dir());
- strcat(opt_path, OPTIONS_SUBDIR "/");
+ get_user_data_dir_with_subdir(opt_path);
strcat(opt_path, filename);
#ifdef TUXMATH_DEBUG
@@ -889,8 +919,8 @@
char opt_path[PATH_MAX];
/* find $HOME and tack on file name: */
- strcpy(opt_path, get_user_data_dir());
- strcat(opt_path, OPTIONS_SUBDIR "/" GOLDSTAR_FILENAME);
+ get_user_data_dir_with_subdir(opt_path);
+ strcat(opt_path, GOLDSTAR_FILENAME);
#ifdef TUXMATH_DEBUG
printf("\nIn read_goldstars() full path to file is: = %s\n", opt_path);
@@ -925,8 +955,8 @@
}
/* find $HOME and add rest of path to config file: */
- strcpy(opt_path, get_user_data_dir());
- strcat(opt_path, OPTIONS_SUBDIR "/" GOLDSTAR_FILENAME);
+ get_user_data_dir_with_subdir(opt_path);
+ strcat(opt_path, GOLDSTAR_FILENAME);
#ifdef TUXMATH_DEBUG
printf("\nIn write_goldstars() full path to file is: = %s\n", opt_path);
@@ -957,8 +987,8 @@
char opt_path[PATH_MAX];
/* find $HOME and tack on file name: */
- strcpy(opt_path, get_user_data_dir());
- strcat(opt_path, OPTIONS_SUBDIR "/" HIGHSCORE_FILENAME);
+ get_user_data_dir_with_subdir(opt_path);
+ strcat(opt_path, HIGHSCORE_FILENAME);
#ifdef TUXMATH_DEBUG
printf("\nIn read_high_scores() full path to file is: = %s\n", opt_path);
@@ -994,8 +1024,8 @@
}
/* find $HOME and add rest of path to config file: */
- strcpy(opt_path, get_user_data_dir());
- strcat(opt_path, OPTIONS_SUBDIR "/" HIGHSCORE_FILENAME);
+ get_user_data_dir_with_subdir(opt_path);
+ strcat(opt_path, HIGHSCORE_FILENAME);
#ifdef TUXMATH_DEBUG
printf("\nIn write_high_scores() full path to file is: = %s\n", opt_path);
@@ -1654,8 +1684,8 @@
}
/* find $HOME and add rest of path to config file: */
- strcpy(opt_path, get_user_data_dir());
- strcat(opt_path, OPTIONS_SUBDIR "/" OPTIONS_FILENAME);
+ get_user_data_dir_with_subdir(opt_path);
+ strcat(opt_path, OPTIONS_FILENAME);
#ifdef TUXMATH_DEBUG
printf("\nIn write_user_config_file() full path to config file is: = %s\n", opt_path);
@@ -2369,8 +2399,7 @@
/* and leaving summary1 available for current game: */
/* find $HOME and tack on file name: */
- strcpy(filepath1, get_user_data_dir());
- strcat(filepath1, OPTIONS_SUBDIR "/");
+ get_user_data_dir_with_subdir(filepath1);
strcat(filepath1, summary_filenames[NUM_SUMMARIES - 1]);
fp = fopen(filepath1, "r");
@@ -2390,20 +2419,17 @@
for (i = NUM_SUMMARIES - 1; i > 0; i--)
{
/* old filename: */
- strcpy(filepath1, get_user_data_dir());
- strcat(filepath1, OPTIONS_SUBDIR "/");
+ get_user_data_dir_with_subdir(filepath1);
+ strcpy(filepath2,filepath1);
strcat(filepath1, summary_filenames[i - 1]);
/* new filename: */
- strcpy(filepath2, get_user_data_dir());
- strcat(filepath2, OPTIONS_SUBDIR "/");
strcat(filepath2, summary_filenames[i]);
/* now change the name: */
rename(filepath1, filepath2);
}
/* summary_filenames[0] (i.e. 'summary1') should now be vacant: */
- strcpy(filepath1, get_user_data_dir());
- strcat(filepath1, OPTIONS_SUBDIR "/");
+ get_user_data_dir_with_subdir(filepath1);
strcat(filepath1, summary_filenames[0]);
fp = fopen(filepath1, "w"); /* "w" means start writing with empty file */
@@ -2435,8 +2461,7 @@
char filepath1[PATH_MAX];
int total_answered;
- strcpy(filepath1, get_user_data_dir());
- strcat(filepath1, OPTIONS_SUBDIR "/");
+ get_user_data_dir_with_subdir(filepath1);
strcat(filepath1, summary_filenames[0]);
fp = fopen(filepath1, "a"); /* "a" means append to end of file */
@@ -2493,16 +2518,9 @@
DIR* dir_ptr;
/* find $HOME */
- strcpy(opt_path, get_user_data_dir());
+ get_user_data_dir_with_subdir(opt_path);
#ifdef TUXMATH_DEBUG
- printf("\nIn find_tuxmath_dir() home directory is: = %s\n", opt_path);
- #endif
-
- /* add rest of path to user's tuxmath dir: */
- strcat(opt_path, OPTIONS_SUBDIR);
-
- #ifdef TUXMATH_DEBUG
printf("\nIn find_tuxmath_dir() tuxmath dir is: = %s\n", opt_path);
#endif
@@ -2522,6 +2540,9 @@
FILE* fp;
int status;
+ if (!add_subdir)
+ return 0; // fail if the user specified a directory, but it doesn't exist
+
/* if user's home has a _file_ named .tuxmath (as from previous version */
/* of program), need to get rid of it or directory creation will fail: */
fp = fopen(opt_path, "r");
@@ -2566,6 +2587,85 @@
}
+/* Utility function to test whether a given dirent represents a directory */
+/* Note this assumes a base of the user's current data directory, it's
+ not a general function. */
+int isdir(const struct dirent *dirEntry)
+{
+ struct stat fileStat;
+ char opt_path[PATH_MAX];
+
+ // Exclude "." from consideration
+ if (strcmp(dirEntry->d_name,".") == 0)
+ return 0;
+ // Exclude ".." from consideration
+ if (strcmp(dirEntry->d_name,"..") == 0)
+ return 0;
+
+ // Prepend the pathname
+ get_user_data_dir_with_subdir(opt_path);
+ strncat(opt_path, dirEntry->d_name,PATH_MAX-strlen(opt_path));
+
+ if (stat(opt_path, &fileStat) < 0) {
+ printf("error parsing %s\n",opt_path);
+ return 0;
+ }
+ printf("Entry: %s, IsDir: %d\n",opt_path, S_ISDIR(fileStat.st_mode));
+ if (S_ISDIR(fileStat.st_mode))
+ return 1;
+ else
+ return 0;
+}
+
+
+/* Checks to see if the current data dir has subdirectories, and if so */
+/* returns their names. This is used in cases where users must select */
+/* their login information. Returns the number of subdirectories (0 if */
+/* there are none), and sets the input argument to a malloc-ed array */
+/* names (sets to NULL if there are no subdirectories). */
+int tuxmath_dir_subdirs(char ***subdir_names)
+{
+ struct dirent **namelist;
+ int n_entries,i;
+ char opt_path[PATH_MAX];
+
+ get_user_data_dir_with_subdir(opt_path);
+ n_entries = scandir(opt_path, &namelist, isdir, alphasort);
+ if (n_entries > 0) {
+ *subdir_names = (char **) malloc(n_entries*sizeof(char*));
+ for (i = 0; i < n_entries; i++)
+ (*subdir_names)[i] = strdup(namelist[i]->d_name);
+ free(namelist);
+ return n_entries;
+ }
+ else {
+ *subdir_names = NULL;
+ return 0;
+ }
+}
+
+/* A utility function to go up one level in a directory hierarchy */
+void dirname_up(char *dirname)
+{
+ int len;
+
+ len = strlen(dirname);
+ printf("up1: len = %d\n",len);
+ // Pass over all trailing "/"
+ while (len > 0 && dirname[len-1] == '/')
+ len--;
+ printf("up2: len = %d\n",len);
+
+ // Now pass over all non-"/" characters at the end
+ while (len > 0 && dirname[len-1] != '/')
+ len--;
+ printf("up3: len = %d\n",len);
+
+ // Terminate the string after that next-to-last "/"
+ dirname[len] = '\0';
+}
+
+
/* Allows use of "true", "YES", T, etc. in text file for boolean values. */
/* Return value of -1 means value string is not recognized. */
static int str_to_bool(const char* val)
Modified: tuxmath/trunk/src/setup.c
===================================================================
--- tuxmath/trunk/src/setup.c 2007-11-23 11:02:43 UTC (rev 342)
+++ tuxmath/trunk/src/setup.c 2007-11-26 06:29:31 UTC (rev 343)
@@ -97,6 +97,7 @@
void setup(int argc, char * argv[])
{
/* initialize settings and read in config files: */
+ /* Note this now only does the global settings */
initialize_options();
/* Command-line code now in own function: */
handle_command_args(argc, argv);
@@ -108,6 +109,8 @@
generate_flipped_images();
/* Generate blended images (e.g., igloos) */
generate_blended_images();
+ /* Note that the per-user options will be set after the call to
+ titlescreen, to allow for user-login to occur. */
}
@@ -115,8 +118,7 @@
/* Set up mathcards with default values for math question options, */
/* set up game_options with defaults for general game options, */
-/* then read in global config file, followed if desired by user's */
-/* own config file: */
+/* then read in global config file */
void initialize_options(void)
{
/* Initialize MathCards backend for math questions: */
@@ -143,8 +145,14 @@
fprintf(stderr, "\nCould not find global config file.\n");
/* can still proceed using hard-coded defaults. */
}
+}
- /* Now read in user-specific settings, if desired. By */
+/* Read in the user-specific options (if desired) */
+/* This has been split from the above to allow it to be called */
+/* from titlescreen, to allow for user-login to occur. */
+void initialize_options_user(void)
+{
+ /* Read in user-specific settings, if desired. By */
/* default, this restores settings from the player's last */
/* game: */
if (Opts_PerUserConfig())
@@ -210,6 +218,12 @@
"to configure the behavior of Tuxmath.\n\n");
printf("Run the game with:\n"
+ "--homedir dirname - seek for user home director(ies) in the specified\n"
+ " location, rather than the user's actual home\n"
+ " directory. You can set up a user directory tree in\n"
+ " this location (see README). This option is\n"
+ " especially useful for schools where all students log\n"
+ " in with a single user name.\n"
"--optionfile filename - read config settings from named file. The locations\n"
" searched for a file with a matching name are the\n"
" current working directory, the absolute path of the\n"
@@ -262,7 +276,23 @@
usage(0, argv[0]);
}
- /* TODO implement --optionfile filename */
+ else if (0 == strcmp(argv[i], "--homedir"))
+ {
+ // Parse the user choice of a non-default home directory
+ if (i >= argc -1)
+ {
+ fprintf(stderr, "%s option requires an argument (dirname)\n", argv[i]);
+ usage(1, argv[0]);
+ }
+ else // see whether the specified name is a directory
+ {
+ if (opendir(argv[i+1]) == NULL)
+ fprintf(stderr,"homedir: %s is not a directory, or it could not be read\n", argv[i+1]);
+ else
+ set_user_data_dir(argv[i+1]); // copy the homedir setting
+ i++; // to pass over the next argument, so remaining options parsed
+ }
+ }
else if (0 == strcmp(argv[i], "--optionfile"))
{
if (i >= argc - 1)
Modified: tuxmath/trunk/src/setup.h
===================================================================
--- tuxmath/trunk/src/setup.h 2007-11-23 11:02:43 UTC (rev 342)
+++ tuxmath/trunk/src/setup.h 2007-11-26 06:29:31 UTC (rev 343)
@@ -33,5 +33,6 @@
void setup(int argc, char * argv[]);
void cleanup(void);
void cleanup_on_error(void);
+extern void initialize_options_user(void);
#endif
Modified: tuxmath/trunk/src/titlescreen.c
===================================================================
--- tuxmath/trunk/src/titlescreen.c 2007-11-23 11:02:43 UTC (rev 342)
+++ tuxmath/trunk/src/titlescreen.c 2007-11-26 06:29:31 UTC (rev 343)
@@ -161,6 +161,8 @@
Uint32 start = 0;
int i;
+ int n_subdirs;
+ char **subdir_names;
if (Opts_UsingSound())
@@ -311,8 +313,13 @@
audioMusicLoad("tuxi.ogg", -1);
}
- /* Start the main menu */
- run_main_menu();
+ /* If necessary, have the user log in */
+ if (run_login_menu() != -1) {
+ /* Finish parsing user options */
+ initialize_options_user();
+ /* Start the main menu */
+ run_main_menu();
+ }
/* User has selected quit, clean up */
@@ -909,9 +916,64 @@
}
+/* Sets the user home directory in a tree of possible users */
+/* -1 indicates that the user wants to quit without logging in, */
+/* 0 indicates that a choice has been made. */
+int run_login_menu(void)
+{
+ menu_options menu_opts;
+ int chosen_login = -1;
+ char *user_home;
+ char **subdir_names;
+ int n_subdirs;
+ int level;
+ char opt_path[PATH_MAX];
+
+ set_default_menu_options(&menu_opts);
+ level = 0;
+ // Get current home directory
+ user_home = get_user_data_dir();
+
+ n_subdirs = tuxmath_dir_subdirs(&subdir_names);
+ while (n_subdirs) {
+ // Get the user choice
+ chosen_login = choose_menu_item(subdir_names, NULL, n_subdirs, menu_opts);
+ if (chosen_login == -1) {
+ // User pressed escape, handle by quitting or going up a level
+ free(subdir_names);
+ if (level == 0)
+ return -1; // Indicate that the user is quitting without logging in
+ else {
+ // Go back up one level of the directory tree
+ printf("Going up a level\n");
+ printf("Previous home: %s\n",user_home);
+ dirname_up(user_home);
+ level--;
+ printf("New home: %s\n",user_home);
+ n_subdirs = tuxmath_dir_subdirs(&subdir_names);
+ }
+ }
+ else {
+ // User chose an entry, set it up
+ strcat(user_home,subdir_names[chosen_login]);
+ strcat(user_home,"/");
+ level++;
+ free(subdir_names);
+ // Keep checking to see if we need to descend further
+ n_subdirs = tuxmath_dir_subdirs(&subdir_names);
+ }
+ }
+ get_user_data_dir_with_subdir(opt_path);
+ printf("User data directory: %s\n", opt_path);
+
+ return 0;
+}
+
+
/****************************************************************/
/* choose_menu_item: menu navigation utility function */
/* (the function returns the index for the selected menu item) */
+/* -1 indicates that the user pressed escape */
/****************************************************************/
int choose_menu_item(const unsigned char **menu_text, sprite **menu_sprites, int n_menu_entries, menu_options menu_opts)
{
More information about the Tux4kids-commits
mailing list