<commit_before>require "nokogiri"
require "net/http"
require "uri"
require "time"
require "facets"
require "yaml"

module Watcard
  class History
    def initialize(config)
      @conf = config
    end

    def log(msg)
      STDERR.puts msg
    end

    def history_page(date)
      uri = URI.parse("https://account.watcard.uwaterloo.ca/watgopher661.asp")
      date_txt = date.strftime("%m/%d/%Y")
      args = {
        "acnt_1"=>@conf['id'],
        "acnt_2"=>@conf['pin'],
        "DBDATE"=>date_txt,
        "DEDATE"=>date_txt,
        "PASS"=>"<PASSWORD>",
        "STATUS"=>"HIST",
        "watgopher_title"=>"WatCard History Report",
        "watgopher_regex"=>'<hr>([\s\S]*wrong[\s\S]*)<p></p>|(<form[\s\S]*?(</center>|</form>))|(<pre><p>[\s\S]*</pre>)',
        "watgopher_style"=>'onecard_narrow',
      }
      log "# Fetching history for #{date}"
      Net::HTTP.post_form(uri, args)
    end

    def parse_loc(loc)
      return "V1 Cafeteria" if loc =~ /WAT-FS-V1/
      return "Liquid Assets" if loc =~ /WAT-FS-LA/
      return "V1 Laundry" if loc =~ /V1 LAUNDRY/
      return "Media.Doc" if loc =~ /MEDIA.DOC/
      loc
    end

    def history(date)
      page_body = history_page(date).body
      doc = Nokogiri::HTML(page_body)
      table = doc.css('#oneweb_financial_history_table')
      table.xpath('.//tr').map do |row|
        cols = row.xpath('./td').map(&:inner_text)
        next if cols.length < 4
        mult = (cols[3] == "1") ? 2 : 1
        {
          time: Time.parse(cols[1], date),
          amount: -(cols[2].strip.to_f)*mult,
          loc: parse_loc(cols.last),
          raw_loc: cols.last,
          balance: cols[3].to_i
        }
      end.compact.reverse
    end

    def add_transaction_types(hist)
      hist.each do |a|
        h = a[:time].hour
        type = if a[:loc] =~ /laundry/i
          "Laundry"
        elsif a[:loc] =~ /media/i
          "Printing"
        elsif h < 11
          "Breakfast"
        elsif h < 17
          "Lunch"
        else
          "Dinner"
        end
        a[:meal] = type
      end
    end

    def bundle_transactions(hist)
      return hist if hist.empty?
      meals = [hist.shift]
      hist.each do |a|
        # if last meal is same type treat them as one
        if a[:meal] == meals.last[:meal]
          meals.last[:amount] += a[:amount]
        else
          meals << a
        end
      end
      meals
    end

    def add_accounts(hist)
      accounts = @conf['accounts']
      hist.each do |a|
        a[:account] = accounts[a[:balance]] || accounts[4]
      end<commit_msg>Add V1 front desk location<commit_after>require "nokogiri"
require "net/http"
require "uri"
require "time"
require "facets"
require "yaml"

module Watcard
  class History
    def initialize(config)
      @conf = config
    end

    def log(msg)
      STDERR.puts msg
    end

    def history_page(date)
      uri = URI.parse("https://account.watcard.uwaterloo.ca/watgopher661.asp")
      date_txt = date.strftime("%m/%d/%Y")
      args = {
        "acnt_1"=>@conf['id'],
        "acnt_2"=>@conf['pin'],
        "DBDATE"=>date_txt,
        "DEDATE"=>date_txt,
        "PASS"=>"PASS",
        "STATUS"=>"HIST",
        "watgopher_title"=>"WatCard History Report",
        "watgopher_regex"=>'<hr>([\s\S]*wrong[\s\S]*)<p></p>|(<form[\s\S]*?(</center>|</form>))|(<pre><p>[\s\S]*</pre>)',
        "watgopher_style"=>'onecard_narrow',
      }
      log "# Fetching history for #{date}"
      Net::HTTP.post_form(uri, args)
    end

    def parse_loc(loc)
      return "V1 Cafeteria" if loc =~ /WAT-FS-V1/
      return "Liquid Assets" if loc =~ /WAT-FS-LA/
      return "V1 Laundry" if loc =~ /V1 LAUNDRY/
      return "V1 Front Desk" if loc =~ /V1DESK/
      return "Media.Doc" if loc =~ /MEDIA.DOC/
      loc.strip
    end

    def history(date)
      page_body = history_page(date).body
      doc = Nokogiri::HTML(page_body)
      table = doc.css('#oneweb_financial_history_table')
      table.xpath('.//tr').map do |row|
        cols = row.xpath('./td').map(&:inner_text)
        next if cols.length < 4
        mult = (cols[3] == "1") ? 2 : 1
        {
          time: Time.parse(cols[1], date),
          amount: -(cols[2].strip.to_f)*mult,
          loc: parse_loc(cols.last),
          raw_loc: cols.last,
          balance: cols[3].to_i
        }
      end.compact.reverse
    end

    def add_transaction_types(hist)
      hist.each do |a|
        h = a[:time].hour
        type = if a[:loc] =~ /laundry/i
          "Laundry"
        elsif a[:loc] =~ /media|desk/i
          "Printing"
        elsif h < 11
          "Breakfast"
        elsif h < 17
          "Lunch"
        else
          "Dinner"
        end
        a[:meal] = type
      end
    end

    def bundle_transactions(hist)
      return hist if hist.empty?
      meals = [hist.shift]
      hist.each do |a|
        # if last meal is same type treat them as one
        if a[:meal] == meals.last[:meal]
          meals.last[:amount] += a[:amount]
        else
          meals << a
        end
      end
      meals
    end

    def add_accounts(hist)
      accounts = @conf['accounts']
      hist.each do |a|
        a[:account] = accounts[a[:balance]] || accounts[4]
      end
{'fraction_non_alphanumeric': 0.1554959785522788, 'fraction_numerical': 0.009000382995021065, 'mean_word_length': 1.954185520361991, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 38, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6474309', 'n_tokens_mistral': 1927, 'n_tokens_neox': 1860, 'n_words': 390}