diff options
Diffstat (limited to 'build-aux/tdat2xml')
-rwxr-xr-x | build-aux/tdat2xml | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/build-aux/tdat2xml b/build-aux/tdat2xml new file mode 100755 index 0000000..1274e32 --- /dev/null +++ b/build-aux/tdat2xml @@ -0,0 +1,294 @@ +#!/usr/bin/env php +<?php +/** + * Generate territory matrices from data files + * + * Copyright (C) 2016 R-T Specialty, LLC. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +?> +<?xml-stylesheet type="text/xsl" href="../../rater/summary.xsl"?> +<lv:package + xmlns:lv="http://www.lovullo.com/rater" + xmlns:c="http://www.lovullo.com/calc" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.lovullo.com/rater ../../rater/rater.xsd" + +<?php + +include 'lib/zipre.php'; + +function parse_tdesc( $line ) +{ + if ( !( preg_match( '/^([0-9A-Z]+) (.+)$/', $line, $match ) ) ) + { + throw new Exception( 'Invalid territory descriptor' ); + } + + return array( $match[ 1 ], $match[ 2 ] ); +} + +function gen_yields( $id, $name ) +{ + return sprintf( 'is%sTerr%s', ucfirst( $name ), $id ); +} + +function gen_classification( $id, $name, $desc, $prev_yields, $queue, $or ) +{ + $yields = gen_yields( $id, $name ); + + $prev_value = ''; + foreach ( $prev_yields as $prev ) + { + if ( !$prev ) + { + continue; + } + + $prev_value .= ' <lv:match on="' . $prev . '" value="FALSE" />' . "\n"; + } + + return sprintf( + '<lv:classify as="%s-terr%s" desc="%s" yields="%s">' . + "\n%s" . + " %s\n" . + "\n</lv:classify>\n", + $name, + gen_identifier( $id ), + $desc, + $yields, + $prev_value, + gen_any_block( $queue, $or ) + ); +} + + +function gen_any_block( $queue, $or ) +{ + $any = gen_zip_re( $queue ) . + gen_on_class( $or ); + + return ( $any ) + ? '<lv:any>' . $any . '</lv:any>' + : ''; +} + + +function gen_zip_re( $data ) +{ + if ( count( $data ) === 0 ) + { + return ''; + } + + return sprintf( + '<lv:match on="zip" pattern="%s" />', + gen_re_quick( $data ) + ); +} + +function gen_on_class( $data ) +{ + if ( count( $data ) === 0 ) + { + return ''; + } + + $cur = array_shift( $data ); + + return sprintf( + '<lv:match on="%s" value="TRUE" />%s', + $cur, + gen_on_class( $data ) + ); +} + +function gen_identifier( $id ) +{ + return is_numeric( $id ) + ? $id + : '-' . strtolower( $id ); +} + +function gen_identifier_value( $id ) +{ + // for non-numeric identifiers, return ascii value + // of character to represent our value + return is_numeric( $id ) + ? $id + : ord( $id ); +} + +$file = $argv[ 1 ]; +$fdat = explode( '.', basename( $file ) ); +$name = $fdat[ 0 ]; + +$cur = ''; +$queue = array(); +$or = array(); + +$fh = fopen( $file, 'r' ); + +echo 'name="rates/territories/', $name, '" ', "\n", + 'desc="', ucfirst( $name ), ' territory classifications">' . "\n\n"; + +echo "<!--\n", + " WARNING: This file was generated by {$argv[0]}; do not modify!\n", + "-->\n\n"; + +$ids = array(); +$params = array(); +$imports = array(); +$prev_yields = ''; +$prev_yields_all = array(); +$classes = ''; + +$param_type = 'terrType' . ucfirst( $name ); + +while ( true ) +{ + // read the line within the loop so that we do not terminate until after we + // treat eof as an empty line + $line = str_replace( array( "\n", "\r" ), '', fgets( $fh ) ); + + if ( !$cur ) + { + if ( substr( $line, 0, 12 ) === '@import-pkg ' ) + { + $imports[] = substr( $line, 12 ); + continue; + } + + // we expect this line to be a territory descriptor + try + { + list ( $id, $desc ) = parse_tdesc( $line ); + } + catch ( Exception $e ) + { + fwrite( STDERR, 'Invalid territory descriptor: ' . $line ); + exit( 1 ); + } + + $ids[] = $id; + $cur = $id; + } + elseif ( ( $line === '' ) || feof( $fh ) ) + { + // generate param for typedef + $params[ $id ] = $desc; + + // if there's nothing in the queue, then treat this as an 'ROS' (this + // should appear as the *last* territory, or it will not function as + // expected) + if ( count( $queue ) === 0 ) + { + $prev = $prev_yields_all; + } + else + { + $prev = array( $prev_yields ); + } + + // generate the classification + $classes .= gen_classification( $id, $name, $desc, $prev, $queue, $or ); + + // this accomplishes two things: (1) avoids regexes if there's a + // previous match and (2) ensures that we cannot possibly match multiple + // territories + $prev_yields = gen_yields( $id, $name ); + $prev_yields_all[] = $prev_yields; + + $cur = ''; + $queue = array(); + $or = array(); + + if ( feof( $fh ) ) + { + break; + } + } + elseif ( $line[0] === '=' ) + { + // =foo means match on classification @yields "foo" + $or[] = substr( $line, 1 ); + } + else + { + $queue[] = $line; + } +} + +$param_name = 'territory_' . $name; +?> + +<?php /* XXX: This is hard-coded! */ ?> +<lv:import package="/rater/core/tdat" /> + +<?php foreach ( $imports as $pkg ) { ?> + <lv:import package="<?php echo $pkg; ?>" /> +<?php } ?> + +<lv:extern name="zip" type="param" dtype="integer" dim="1" + missing="this territory package requires an available `zip' parameter; please + import a package that provides it" /> + +<lv:param name="<?php echo $param_name; ?>" type="<?php echo $param_type; ?>" default="0" set="vector" desc="Territory Override" /> + +<lv:typedef name="<?php echo $param_type; ?>" desc="<?php echo ucfirst( $name ); ?> Territories"> + <lv:enum type="integer"> + <?php $item_prefix = 'TERR_' . strtoupper( $name ) . '_'; ?> + <lv:item name="<?php echo $item_prefix; ?>_NONE" value="0" desc="No Override" /> + <?php foreach ( $params as $id => $desc ) { ?> + <?php $item_name = $item_prefix . $id; ?> + <lv:item name="<?php echo $item_name; ?>" value="<?php echo gen_identifier_value( $id ); ?>" desc="<?php echo $desc; ?>" /> + <?php } ?> + </lv:enum> +</lv:typedef> + +<?php echo $classes; ?> + +<lv:section title="Territory Determination"> + <?php foreach ( $ids as $id ) { ?> + <?php $yields = sprintf( '%sTerr%s', $name, $id ); ?> + <?php $class = sprintf( '%s-terr%s', $name, gen_identifier( $id ) ); ?> + <lv:apply-template name="_terr-code_" class="<?php echo $class; ?>" code="<?php echo gen_identifier_value( $id ); ?>" generates="<?php echo $yields; ?>" /> + <?php } ?> + + <lv:rate yields="_<?php echo $name; ?>TerrCode"> + <c:sum of="zip" index="k" generates="<?php echo $name; ?>TerrCode" desc="Territory code"> + <c:cases> + <c:case> + <c:when name="<?php echo $param_name; ?>" index="k"> + <c:gt> + <c:const value="0" type="integer" desc="Use territory override if set" /> + </c:gt> + </c:when> + + <c:value-of name="<?php echo $param_name; ?>" index="k" /> + </c:case> + + <c:otherwise> + <c:sum label="Determine applicable territory code"> + <?php foreach ( $ids as $id ) { ?> + <c:value-of name="<?php echo $name; ?>Terr<?php echo $id; ?>" index="k" /> + <?php } ?> + </c:sum> + </c:otherwise> + </c:cases> + </c:sum> + </lv:rate> +</lv:section> +</lv:package> |