Root/old-boom/part2order

1#!/usr/bin/perl
2
3require "parser.pl";
4require "misc.pl";
5
6$mult = shift(@ARGV);
7&parse;
8
9
10sub number
11{
12    local ($id) = @_;
13
14    my $s = $inv{$id}[0];
15    my $n = $want{$id}*$mult;
16    return $n < $s ? $n : $s;
17
18}
19
20
21#
22# The heuristics here aren't very nice. We give zero-cost stock priority over
23# any other stock, when we go by stock size up to the quantity we need. The
24# idea is to exhause local stock (zero-cost) first, then try to obtain the
25# parts with as few orders as possible.
26#
27# It would be better to have some sort of priority, so that we can express a
28# preference among stock we already own. Also, if non-zero-cost stock has widly
29# different prices, the smallest order cost may not be a good indicator of
30# which source we prefer.
31#
32# Furthermore, the algorithm doesn't consider the number of sources we use in
33# total or things like lead time, shipping cost, customs, etc.
34#
35
36sub rank
37{
38    local ($a, $b) = @_;
39
40    my $na = &number($a); # min(number wanted, available)
41    my $nb = &number($b);
42    my $pa = $inv{$a}[3]; # per unit price for smallest quantum
43    my $pb = $inv{$b}[3];
44
45#print STDERR "a=$a b=$b na=$na nb=$nb pa=$pa pb=$pb\n";
46    return 1 if $na && !$pa && $pb;
47    return -1 if $nb && $pa && !$pb;
48    return $na <=> $nb if $na != $nb;
49    return $pb <=> $pa;
50}
51
52
53for (keys %parts) {
54    $parts++;
55}
56
57print "#ORD\n";
58for (sort { &rank($b, $a) } keys %want) {
59    my $n = &number($_);
60    $n -= $n % $mult;
61    next unless $n;
62    my @f = @{ $inv{$_} };
63    my $max = shift @f;
64    my $currency = shift @f;
65    my @qty;
66    my @price;
67    my %index;
68    my $best_qty;
69    my $best_price = undef;
70    while (@f) {
71    my $q = shift @f;
72    my $p = shift @f;
73    if (defined $index{$q}) {
74        $price[$index{$q}] = $p;
75    } else {
76        push(@qty, $q);
77        push(@price, $p);
78        $index{$q} = $#qty;
79        # @@@ this fails if smaller quantities following a large quantity
80        # differ from the quantities preceding them. E.g., 1 10 100 25
81        # wouldn't yield correct results.
82    }
83    for (my $i = $#qty; $i >= 0; $i--) {
84        my $order = 0;
85        my $price = 0;
86        my $left = $n;
87        for (my $j = $#qty; $j >= $i; $j--) {
88        while ($left >= ($j == $i ? 1 : $qty[$j])) {
89            $left -= $qty[$j];
90            $order += $qty[$j];
91            $price += $price[$j]*$qty[$j];
92        }
93        }
94        next if $order > $max;
95        if (!defined $best_price || $price < $best_price) {
96        $best_price = $price;
97        $best_qty = $order;
98        }
99    }
100    }
101    next if !defined $best_price;
102    print "$_ $best_qty $currency $best_price";
103    my $id = $_;
104    while (keys %{ $comps{$id} }) {
105    last if $best_qty < $mult;
106    $best_qty -= $mult;
107    my $ref = (sort { &cmp_cref($a, $b); } keys %{ $comps{$id} })[0];
108#print STDERR "$id: $ref + ", join("|", keys %{ $comps{$id} }), "\n";
109    my @f = @{ $parts{$ref} };
110    while (@f) {
111        my @id2 = splice(@f, 0, 2);
112        my $id2 = "$id2[0] $id2[1]";
113        $want{$id2}--;
114        delete $comps{$id2}{$ref};
115    }
116    print " $ref";
117    }
118    print "\n";
119}
120
121for my $id (sort { $want{$b} <=> $want{$a} } keys %want) {
122    next unless $want{$id};
123    print STDERR "$id";
124    for (&eq($id)) {
125# next unless $want{$_};
126    die "\n$_ ($want{$_}) vs. $id want ($want{$id})"
127      unless $want{$_} == $want{$id};
128    print STDERR " $_";
129    $want{$_} = 0;
130    }
131    print STDERR ": want $want{$id}\n";
132    $want{$id} = 0;
133}
134

Archive Download this file

Branches:
master



interactive