old_contents: # Generates resources/weather_rate.js
  
  # (1) Download https://github.com/ufx/SaintCoinach/releases/latest
  # (2) SaintCoinach.Cmd.exe "C:\Program Files (x86)\SquareEnix\FINAL FANTASY XIV - A Realm Reborn"
  # (3) exd TerritoryType WeatherRate
  # (4) Run util/gen_weather_rate.py -f path/to/WeatherRate.csv
  
  import argparse
  import csv
  import json
  import os
  import re
  
  
  def read_data(csvfile):
      all_rates = {}
      reader = csv.reader(csvfile)
      # skip the first three header lines
      next(reader)
      next(reader)
      next(reader)
  
      for row in reader:
          sum = 0
          weathers = []
          rates = []
          for i in range(1, len(row), 2):
              weather_name = row[i]
              if not weather_name:
                  break
              weathers.append(weather_name)
              sum += int(row[i+1])
              rates.append(sum)
          # add leading zeroes so they sort properly.
          all_rates["%04d" % int(row[0])] = {
              'weathers': weathers,
              'rates': rates,
          }
      return all_rates
  
  
  def write_file(output, all_rates):
      output.write("'use strict';\n\n")
      output.write('// Auto-generated from ' + __file__ + '\n')
      output.write('// DO NOT EDIT THIS FILE DIRECTLY\n\n')
      output.write('let gWeatherRates = ')
      str = json.dumps(all_rates, sort_keys=True, indent=2)
      # single quote style
      str = re.sub(r'"', "'", str)
      # add trailing commas
      str = re.sub(r"([0-9]|'|]|})\s*$", r"\1,", str, flags=re.MULTILINE)
      # remove final trailing comma
      str = re.sub(r",$", "", str)
      # make keys integers, remove leading zeroes.
      str = re.sub(r"'0*([0-9]+)': {", r"\1: {", str)
      output.write(str)
      output.write(';\n')
  
  
  def main(args):
      with open(args.file, 'r') as csvfile:
          all_rates = read_data(csvfile)
      with open(args.output, 'w') as output:
          write_file(output, all_rates)
  
  
  if __name__ == "__main__":
      example_usage = ""
  
      parser = argparse.ArgumentParser(
          description="Generates weather_rate.js from exported WeatherRate.csv",
          epilog=example_usage,
          formatter_class=argparse.RawDescriptionHelpFormatter)
  
      parser.add_argument('-f', '--file', help="The WeatherRate.csv file")
      parser.add_argument('-o', '--output', help="The file to write")
  
      args = parser.parse_args()
  
      if not args.file:
          raise parser.error('Must pass a file.')
      if not args.output:
          args.output = os.path.join(os.path.dirname(__file__), '../resources/weather_rate.js')
      main(args)
  
new_contents: import csv
  import coinach
  import os
  
  _OUTPUT_FILE = 'weather_rate.js'
  
  
  def parse_data(csvfile):
      all_rates = {}
      reader = csv.reader(csvfile)
      # skip the first three header lines
      next(reader)
      next(reader)
      next(reader)
  
      for row in reader:
          sum = 0
          weathers = []
          rates = []
          for i in range(1, len(row), 2):
              weather_name = row[i]
              if not weather_name:
                  break
              weathers.append(weather_name)
              sum += int(row[i+1])
              rates.append(sum)
          # add leading zeroes so they sort properly.
          all_rates["%04d" % int(row[0])] = {
              'weathers': weathers,
              'rates': rates,
          }
      return all_rates
  
  
  def update(reader, writer):
      data = reader.exd('WeatherRate')
      all_rates = parse_data(data)
      writer.write(
          os.path.join('resources', _OUTPUT_FILE),
          os.path.basename(os.path.abspath(__file__)),
          'gWeatherRates',
          all_rates)
  
  
  if __name__ == "__main__":
      # TODO: make an arg parser for non-default paths
      reader = coinach.CoinachReader(verbose=True)
      writer = coinach.CoinachWriter(verbose=True)
      update(reader, writer)
  
subject: update gen_weather_rate to use helper