xref: /inferno-os/appl/lib/scoretable.b (revision 9b29ac7ea714507a9c0690620c02c8ca5ab25f90)
137da2899SCharles.Forsyth# Copyright  © 1999 Roger Peppe.  All rights reserved.
237da2899SCharles.Forsythimplement Scoretable;
337da2899SCharles.Forsythinclude "sys.m";
437da2899SCharles.Forsyth	sys: Sys;
537da2899SCharles.Forsyth	stderr: ref Sys->FD;
637da2899SCharles.Forsythinclude "draw.m";
737da2899SCharles.Forsythinclude "bufio.m";
837da2899SCharles.Forsyth	bufio: Bufio;
937da2899SCharles.Forsyth	Iobuf: import bufio;
1037da2899SCharles.Forsythinclude "scoretable.m";
1137da2899SCharles.Forsyth
1237da2899SCharles.Forsyth# this is the cut-down version - it doesn't bother
1337da2899SCharles.Forsyth# with score table locking at all; there is such a version,
1437da2899SCharles.Forsyth# but it needs a lock server, so is often more hassle than
1537da2899SCharles.Forsyth# it's worth. if you want a distributed score file, contact
1637da2899SCharles.Forsyth# rog@vitanuova.com
1737da2899SCharles.Forsyth# currently this module is only used by tetris - the interface
1837da2899SCharles.Forsyth# will probably change in the future.
1937da2899SCharles.Forsyth
2037da2899SCharles.Forsythscorefile: string;
2137da2899SCharles.Forsythusername: string;
2237da2899SCharles.Forsyth
2337da2899SCharles.ForsythMAXSCORES: con 10;
2437da2899SCharles.Forsyth
25*9b29ac7eSCharles.Forsythinit(nil: int, user, nil: string, sfile: string): (int, string)
2637da2899SCharles.Forsyth{
2737da2899SCharles.Forsyth	if (sys == nil) {
2837da2899SCharles.Forsyth		sys = load Sys Sys->PATH;
2937da2899SCharles.Forsyth		stderr = sys->fildes(2);
3037da2899SCharles.Forsyth		bufio = load Bufio Bufio->PATH;
3137da2899SCharles.Forsyth		if (bufio == nil) {
3237da2899SCharles.Forsyth			sys = nil;
3337da2899SCharles.Forsyth			return (-1, sys->sprint("cannot load %s: %r", Bufio->PATH));
3437da2899SCharles.Forsyth		}
3537da2899SCharles.Forsyth	}
3637da2899SCharles.Forsyth	username = user;
3737da2899SCharles.Forsyth	lock();
3837da2899SCharles.Forsyth	scorefd: ref Sys->FD;
3937da2899SCharles.Forsyth	if ((scorefd = sys->open(sfile, Sys->ORDWR)) == nil
4037da2899SCharles.Forsyth	&& (scorefd = sys->create(sfile, Sys->ORDWR, 8r666)) == nil) {
4137da2899SCharles.Forsyth		unlock();
4237da2899SCharles.Forsyth		return (-1, sys->sprint("cannot open %s: %r", sfile));
4337da2899SCharles.Forsyth	}
4437da2899SCharles.Forsyth	unlock();
4537da2899SCharles.Forsyth	scorefile = sfile;
4637da2899SCharles.Forsyth	return (0, nil);
4737da2899SCharles.Forsyth}
4837da2899SCharles.Forsyth
4937da2899SCharles.Forsythlock()
5037da2899SCharles.Forsyth{
5137da2899SCharles.Forsyth}
5237da2899SCharles.Forsyth
5337da2899SCharles.Forsythunlock()
5437da2899SCharles.Forsyth{
5537da2899SCharles.Forsyth}
5637da2899SCharles.Forsyth
5737da2899SCharles.Forsythscores(): list of Score
5837da2899SCharles.Forsyth{
5937da2899SCharles.Forsyth	lock();
6037da2899SCharles.Forsyth	sl := readscores();
6137da2899SCharles.Forsyth	unlock();
6237da2899SCharles.Forsyth	return sl;
6337da2899SCharles.Forsyth}
6437da2899SCharles.Forsyth
6537da2899SCharles.Forsythreadscores(): list of Score
6637da2899SCharles.Forsyth{
6737da2899SCharles.Forsyth	sl: list of Score;
6837da2899SCharles.Forsyth	iob := bufio->open(scorefile, Sys->OREAD);
6937da2899SCharles.Forsyth	if (iob == nil)
7037da2899SCharles.Forsyth		return nil;
7137da2899SCharles.Forsyth	iob.seek(big 0, Bufio->SEEKSTART);
7237da2899SCharles.Forsyth	while ((s := iob.gets('\n')) != nil) {
7337da2899SCharles.Forsyth		(n, toks) := sys->tokenize(s, " \t\n");
7437da2899SCharles.Forsyth		if (toks == nil)
7537da2899SCharles.Forsyth			continue;
7637da2899SCharles.Forsyth		if (n < 2) {
7737da2899SCharles.Forsyth			sys->fprint(stderr, "bad line in score table: %s", s);
7837da2899SCharles.Forsyth			continue;
7937da2899SCharles.Forsyth		}
8037da2899SCharles.Forsyth		score: Score;
8137da2899SCharles.Forsyth		(score.user, toks) = (hd toks, tl toks);
8237da2899SCharles.Forsyth		(score.score, toks) = (int hd toks, tl toks);
8337da2899SCharles.Forsyth		score.other = nil;
8437da2899SCharles.Forsyth		while (toks != nil) {
8537da2899SCharles.Forsyth			score.other += hd toks;
8637da2899SCharles.Forsyth			if (tl toks != nil)
8737da2899SCharles.Forsyth				score.other += " ";
8837da2899SCharles.Forsyth			toks = tl toks;
8937da2899SCharles.Forsyth		}
9037da2899SCharles.Forsyth		sl = score :: sl;
9137da2899SCharles.Forsyth	}
9237da2899SCharles.Forsyth	iob.close();
9337da2899SCharles.Forsyth	nl: list of Score;
9437da2899SCharles.Forsyth	while (sl != nil) {
9537da2899SCharles.Forsyth		nl = hd sl :: nl;
9637da2899SCharles.Forsyth		sl = tl sl;
9737da2899SCharles.Forsyth	}
9837da2899SCharles.Forsyth	return nl;
9937da2899SCharles.Forsyth}
10037da2899SCharles.Forsyth
10137da2899SCharles.Forsythwritescores(sl: list of Score)
10237da2899SCharles.Forsyth{
10337da2899SCharles.Forsyth	scoreiob := bufio->open(scorefile, Sys->OWRITE|Sys->OTRUNC);
10437da2899SCharles.Forsyth	if (scoreiob == nil) {
10537da2899SCharles.Forsyth		sys->fprint(stderr, "scoretable: cannot write score file '%s': %r\n", scorefile);
10637da2899SCharles.Forsyth		return;
10737da2899SCharles.Forsyth	}
10837da2899SCharles.Forsyth	scoreiob.seek(big 0, Bufio->SEEKSTART);
10937da2899SCharles.Forsyth	n := 0;
11037da2899SCharles.Forsyth	while (sl != nil && n < MAXSCORES) {
11137da2899SCharles.Forsyth		s := hd sl;
11237da2899SCharles.Forsyth		scoreiob.puts(sys->sprint("%s %d %s\n", s.user, s.score, s.other));
11337da2899SCharles.Forsyth		n++;
11437da2899SCharles.Forsyth		sl = tl sl;
11537da2899SCharles.Forsyth	}
11637da2899SCharles.Forsyth	scoreiob.close();
11737da2899SCharles.Forsyth}
11837da2899SCharles.Forsyth
11937da2899SCharles.Forsythsetscore(score: int, other: string): int
12037da2899SCharles.Forsyth{
12137da2899SCharles.Forsyth	lock();
12237da2899SCharles.Forsyth	sl := readscores();
12337da2899SCharles.Forsyth	nl: list of Score;
12437da2899SCharles.Forsyth	done := 0;
12537da2899SCharles.Forsyth	n := rank := 0;
12637da2899SCharles.Forsyth	while (sl != nil) {
12737da2899SCharles.Forsyth		s := hd sl;
12837da2899SCharles.Forsyth		if (score > s.score && !done) {
12937da2899SCharles.Forsyth			nl = Score(username, score, other) :: nl;
13037da2899SCharles.Forsyth			rank = n;
13137da2899SCharles.Forsyth			done = 1;
13237da2899SCharles.Forsyth		}
13337da2899SCharles.Forsyth		nl = s :: nl;
13437da2899SCharles.Forsyth		sl = tl sl;
13537da2899SCharles.Forsyth		n++;
13637da2899SCharles.Forsyth	}
13737da2899SCharles.Forsyth	if (!done) {
13837da2899SCharles.Forsyth		nl = Score(username, score, other) :: nl;
13937da2899SCharles.Forsyth		rank = n;
14037da2899SCharles.Forsyth	}
14137da2899SCharles.Forsyth	sl = nil;
14237da2899SCharles.Forsyth	while (nl != nil) {
14337da2899SCharles.Forsyth		sl = hd nl :: sl;
14437da2899SCharles.Forsyth		nl = tl nl;
14537da2899SCharles.Forsyth	}
14637da2899SCharles.Forsyth	writescores(sl);
14737da2899SCharles.Forsyth	unlock();
14837da2899SCharles.Forsyth	# XXX minor race condition in returning the rank, not our idea of the rank.
14937da2899SCharles.Forsyth	return rank;
15037da2899SCharles.Forsyth}
151