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