chiark / gitweb /
Merge branch 'master' of chiark:/home/ijackson/things/ypp-sc-tools
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Tue, 9 Jun 2009 23:56:04 +0000 (00:56 +0100)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Tue, 9 Jun 2009 23:56:04 +0000 (00:56 +0100)
Conflicts:

pctb/yppsc-decode-marketdata

pctb/example [new file with mode: 0644]
pctb/yppsc-commod-processor
pctb/yppsc-decode-marketdata

diff --git a/pctb/example b/pctb/example
new file mode 100644 (file)
index 0000000..b11651d
--- /dev/null
@@ -0,0 +1,85 @@
+
+
+
+Version number (3 ascii digits) followed
+by LF (i.e. 0x0A).  Current version is\
+ 005
+
+  0000   30 30 35 0a                                        005.
+
+# of shops/stalls (in ascii)  + LF
+  0000               31 0a                                      1.           
+
+list of shop names in ascii (without the
+possessive part and by specifying the \
+shop type in an abbreviated way which is
+mentioned below).  The shop names are
+separated \ by line feeds (0x0A).  To
+specify the shop type append the "^"
+character and then \ one of the
+following characters depending upon the
+shop type:
+   Apothecary = A
+   Distillery = D
+   Furnisher = F
+   Iron Monger = I
+   Shipyard = S
+   Tailor = T
+   Weavery = W
+
+  0000                     4f 6c  64 20 49 72 6f 6e 73 69         Ol d Ironsi
+  0010   64 65 73 0a                                        des.              
+
+# of buy offers (in binary)
+  0010               05 00                                 
+
+commodIndex offerCount                                       buy 0/5
+  0010                     0a 00  01 00                      Grog x 1
+[shopIndex val amt]                   
+  0010                                  01 00 1d 00 75 00    OI 29 qty 75
+
+commodIndex offerCount                                       buy 1/5
+  0020   0b 00 01 00                                         Fine x 1
+[shopIndex val amt]... (all in binar\ y)
+  0020               01 00 33 00  e9 03                      OI 51 qty 0x3e9
+
+commodIndex offerCount                                       buy 2/5
+  0020                                  0c 00 01 00          Small shot x 1
+[shopIndex val amt]
+  0020                                              01 00    OI
+  0030   0f 00 e9 03                                         15 qty 0x3e9
+
+commodIndex offerCount                                       buy 3/5
+  0030               0d 00 01 00                             Medium shot x 1
+[shopIndex val amt]
+  0030                            01 00 1c 00 e9 03          OI 28 qty 0x3e9
+
+commodIndex offerCount                                       buy 4/5
+  0030                                              0e 00    Large shot
+  0040   01 00                                                          x 1
+[shopIndex val amt]
+  0040         01 00 26 00 e9 03                             OI 38 0x3e9
+
+
+# of sell offers (in binary)
+  0040                            04 00
+
+commodIndex offerCount                                       sell 0/4
+  0040                                  09 00 01 00          Swill x 1
+[shopIndex val amt]
+  0040                                              01 00    OI 
+  0050   17 00 e8 03                                         23 0x3e8
+commodIndex offerCount                                       sell 1/4
+  0050               0a 00 01 00                             Grog x 1
+[shopIndex val amt]
+  0050                            01 00 1e 00 73 03          OI 30 qty 0x373
+commodIndex offerCount                                       sell 2/4
+  0050                                              0c 00    Small shot
+  0060   01 00                                               x 1
+[shopIndex val amt]
+  0060         01 00 10 00 07 00                             OI 16 qty 7
+commodIndex offerCount                                       sell 3/4
+  0060                            0d 00 01 00                Medium shot x 1
+[shopIndex val amt]
+  0060                                        01 00 1e 00    OI 30
+  0070   02 00                                               qty 2
index 0e1a7d0..5782a5a 100755 (executable)
 
 
 use strict (qw(vars));
-use Data::Dumper;
+use HTTP::Request;
+use IO::File;
+use POSIX;
+use LWP::UserAgent;
+use XML::Parser;
 
 # $commod{'Hemp'}{Buy|Sell}{'stall'}{Stall}
 # $commod{'Hemp'}{Buy|Sell}{'stall'}{Price}
@@ -88,8 +92,6 @@ sub bs_p_bestprice ($) {
     }
 }
 
-our $arbitrage_only= 0;
-
 sub main__arbitrage () {
     my @arbs= ();
     foreach $commod (sort keys %commod) {
@@ -182,8 +184,6 @@ sub main__bestprices () {
        $current= $commod{$commod};
        my $buys=  bs_p($commod,Buy, -1);
        my $sells= bs_p($commod,Sell,+1);
-       if ($arbitrage_only) {
-       }
        printf("%-15.15s", $commod) or die $!;
        bs_p_bestprice($buys);
        bs_p_bestprice($sells);
@@ -216,10 +216,156 @@ sub main__tsv () {
     }
 }
 
+
+our (%commodmap);
+our ($pctb) = 'http://pctb.ilk.org/';
+our ($ua);
+
+sub load_commodmap() {
+    undef %commodmap;
+    my $c= new IO::File "#commodmap#.tsv";
+    if (!$c) { $!==&ENOENT or die $!; return; }
+    while (<$c>) {
+       m/^(\S.*\S)\t(\d+)\n$/ or die "$_";
+       $commodmap{$1}= $2;
+    }
+    $c->error and die $!;
+    close $c;
+}
+
+sub refresh_commodmap() {
+    my $ua= LWP::UserAgent->new;
+    my $resp= $ua->get("$pctb/commodmap.php?version=2");
+    die $resp->status_line unless $resp->is_success;
+
+    my $cdata='';
+    my $incommodmap=0;
+    my $intag='';
+    my %got;
+    my $o= new IO::File "#commodmap#.tsv.new",'w' or die $!;
+    undef %commodmap;
+
+    my $xp= new XML::Parser
+       (Handlers =>
+        {
+            Start => sub {
+                $_=$_[1];
+#print STDERR "START [$_] intag=$intag icm=$incommodmap\n";
+                if (m/^commodmap$/i) {
+                    $incommodmap++;
+                    undef %got;
+                } elsif (m/^(?:name|index)$/i) {
+                    $cdata='';
+                    $intag=lc($_) if $incommodmap;
+#print STDERR "START RECOGNISED $intag icm=$incommodmap\n";
+#               } else {
+#print STDERR "START UNRECOGNISED\n";
+                }
+            },
+            End => sub {
+                $_=$_[1];
+#print STDERR "END [$_] intag=$intag icm=$incommodmap\n";
+                if (m/^commodmap$/i) {
+                    $incommodmap--;
+                    die unless exists $got{'name'};
+                    die unless exists $got{'index'};
+                    die unless $got{'index'} =~ m/^\s*([1-9]\d{0,3})\s*$/;
+                    my $index= $1;
+                    $_= $got{'name'};
+                    s/^\s+//; s/\s+$//; s/\n/ /g; s/\s+/ /;
+                    die "$_ ?" if exists $commodmap{$_};
+                    $commodmap{$_}= $index;
+                    print $o "$_\t$index\n" or die $!;
+                } elsif (lc $_ eq $intag) {
+                    $got{$intag}= $cdata;
+                }
+            },
+            Char => sub {
+#print STDERR "CHAR [$_[1]] intag=$intag icm=$incommodmap\n";
+                $cdata .= $_[1];
+            }
+        }) or die;
+    my $content= $resp->content;
+
+#    print STDERR "[[[$content]]]\n";
+    $xp->parse($content);
+    close $o or die $!;
+    rename "#commodmap#.tsv.new","#commodmap#.tsv" or die $!;
+}
+
+our (%stallmap, @stallmap);
+
+sub bs_gen_md ($$) {
+    my ($bs,$sortmul) = @_;
+    my $count= 0;
+    my $o= '';
+    
+    foreach $commod (sort {
+       $commodmap{$a} <=> $commodmap{$b}
+    } keys %commod) {
+#print STDERR "COMMOD $commod\n";
+        $current= $commod{$commod};
+       my $l= bs_p($commod,$bs,$sortmul);
+       next unless @$l;
+#print STDERR "COMMOD $commod @$l\n";
+
+       $o .= writeint(scalar @$l);
+       foreach my $cs (@$l) {
+           $stall= $cs->{Stall};
+           my $stallix= $stallmap{$stall};
+           if (!defined $stallix) {
+               push @stallmap, $stall;
+               $stallmap{$stall}= $stallix= @stallmap;
+           }
+           my $qty= $cs->{Qty};
+           $qty =~ s/^\>\s*//;
+           $o .= writeint($stallix, $cs->{Price}, $qty+0);
+           $count++;
+       }
+    }
+#print STDERR "COMMOD $commod COUNT WAS $count\n";
+    return
+       writeint($count).$o;
+}
+
+sub writeint { return pack 'v*', @_; }
+
+sub main__genmarketdata () {
+    our $version= '005b';
+
+    load_commodmap();
+    my @missing= grep { !exists $commodmap{$_} } keys %commod;
+    if (@missing) {
+       refresh_commodmap();
+       my $missing=0;
+       foreach $commod (sort keys %commod) {
+           next if exists $commodmap{$commod};
+           printf STDERR "Unknown commodity \`%s'!\n", $commod;
+           $missing++;
+       }
+       die "$missing unknown commoditi(es).  OCR failure?\n"
+           if $missing;
+    }    
+
+    my $o='';
+    $o .= bs_gen_md(Buy, -1);
+    $o .= bs_gen_md(Sell,+1);
+
+    printf("$version\n".
+          "%d\n",
+          scalar(@stallmap))
+       or die $!;
+    foreach $stall (@stallmap) { print "$stall\n" or die $!; }
+
+    print $o or die$!;
+}
+
+
 sub main__upload () {
     die "\nUploading not yet implemented, sorry.\n";
 }
 
+
 $mode =~ s/\-//;
 &{"main__$mode"};
 close(STDOUT) or die $!;
index e8f0ef0..d798aad 100755 (executable)
@@ -2,9 +2,10 @@
 
 use IO::Handle;
 
+open CM, "#commodmap#.tsv" or die $!;
+
 $debug=1 if @ARGV;
 
-open CM, "commodmap" or die $!;
 while (<CM>) {
     m/^(\S.*\S)\t(\d+)$/ or die;
     $commodmap[$2]= $1;