<commit_before>
moment = require 'moment-timezone'
weekend = require 'moment-weekend'
uuid = require 'node-uuid'

{ HEADERS, MODES, REGEX, TIMEZONE } = require '../helpers/constants'
Logger = require('../helpers/logger')()
Organization = require('./organization').get()

class Punch
  constructor: (@mode = 'none',
                @times = [],
                @projects = [],
                @notes = '') ->
    # ...

  @parse: (user, command, mode='none', timezone) ->
    if not user
      Logger.error 'No user passed', new Error(command)
      return
    else if not command
      Logger.error 'No command passed', new Error(user)
      return
    if mode and mode isnt 'none'
      [mode, command] = _parseMode command

    original = command.slice 0

    [start, end] = user.activeHours()
    tz = timezone || user.timetable.timezone.name
    [times, command] = _parseTime command, start, end, timezone
    [dates, command] = _parseDate command

    datetimes = []
    if dates.length is 0 and times.length is 0
      datetimes.push(moment.tz(tz))
    else if dates.length > 0 and times.length is 0
      datetimes.push(_mergeDateTime(dates[0], start, tz))
      datetimes.push(_mergeDateTime(dates[dates.length - 1], end, tz))
    else if dates.length is 0 and times.length > 0
      for time in times
        datetimes.push(_mergeDateTime(moment.tz(tz), time, tz))
    else
      if dates.length is 2 and times.length is 2
        datetimes.push(_mergeDateTime(dates[0], times[0], tz))
        datetimes.push(_mergeDateTime(dates[1], times[1], tz))
      else if dates.length is 2 and times.length is 1
        datetimes.push(_mergeDateTime(dates[0], times[0], tz))
        datetimes.push(_mergeDateTime(dates[1], times[0], tz))
      else if dates.length is 1 and times.length is 2
        datetimes.push(_mergeDateTime(dates[0], times[0], tz))
        datetimes.push(_mergeDateTime(dates[0], times[1], tz))
      else
        datetimes.push(_mergeDateTime(dates[0], times[0], tz))

    if times.block?
      datetimes.block = times.block
      if datetimes[0]
        date = moment.tz(datetimes[0], tz)
      while datetimes.length isnt 0
        datetimes.pop()
      if mode is 'in'
        mode = 'none'
    else if datetimes.length is 2
      if mode is 'out'
        Logger.error 'An out-punch cannot be a range', new Error(original)
        return
      if datetimes[1].isBefore datetimes[0]
        datetimes[1] = datetimes[1].add(1, 'days')
      elapsed = _calculateElapsed datetimes[0], datetimes[1], mode, user
      if mode is 'in'
        mode = 'none'

    [projects, command] = _parseProjects command
    notes = command.trim()

    punch = new Punch(mode, datetimes, projects, notes)
    punch.date = datetimes[0] || date || moment.tz(tz)
    punch.timezone = tz
    if elapsed
      punch.elapsed = elapsed
    punch
  
  @parseRaw: (user, row, projects = []) ->
    if not user
      return
    else if not row
      return
    else if not row.save or not row.del
      return
    headers = HEADERS.rawdata
    date = moment.tz(row[headers.today], 'MM/DD/YYYY', TIMEZONE)
    if row[headers.project1] is 'vacation' or
       row[headers.project1] is 'sick' or
       row[headers.project1] is 'unpaid'
      mode = row[headers.project1]
    else if row[headers.in] and not row[headers.out]
      mode = 'in'
    else if row[headers.out] and row[headers.totalTime]
      mode = 'out'
    else
      mode = 'none'
    datetimes = []
    tz = user.timetable.timezone.name<commit_msg>Added UUID sanity check<commit_after>
moment = require 'moment-timezone'
weekend = require 'moment-weekend'
uuid = require 'node-uuid'

{ HEADERS, MODES, REGEX, TIMEZONE } = require '../helpers/constants'
Logger = require('../helpers/logger')()
Organization = require('./organization').get()

class Punch
  constructor: (@mode = 'none',
                @times = [],
                @projects = [],
                @notes = '') ->
    # ...

  @parse: (user, command, mode='none', timezone) ->
    if not user
      Logger.error 'No user passed', new Error(command)
      return
    else if not command
      Logger.error 'No command passed', new Error(user)
      return
    if mode and mode isnt 'none'
      [mode, command] = _parseMode command

    original = command.slice 0

    [start, end] = user.activeHours()
    tz = timezone || user.timetable.timezone.name
    [times, command] = _parseTime command, start, end, timezone
    [dates, command] = _parseDate command

    datetimes = []
    if dates.length is 0 and times.length is 0
      datetimes.push(moment.tz(tz))
    else if dates.length > 0 and times.length is 0
      datetimes.push(_mergeDateTime(dates[0], start, tz))
      datetimes.push(_mergeDateTime(dates[dates.length - 1], end, tz))
    else if dates.length is 0 and times.length > 0
      for time in times
        datetimes.push(_mergeDateTime(moment.tz(tz), time, tz))
    else
      if dates.length is 2 and times.length is 2
        datetimes.push(_mergeDateTime(dates[0], times[0], tz))
        datetimes.push(_mergeDateTime(dates[1], times[1], tz))
      else if dates.length is 2 and times.length is 1
        datetimes.push(_mergeDateTime(dates[0], times[0], tz))
        datetimes.push(_mergeDateTime(dates[1], times[0], tz))
      else if dates.length is 1 and times.length is 2
        datetimes.push(_mergeDateTime(dates[0], times[0], tz))
        datetimes.push(_mergeDateTime(dates[0], times[1], tz))
      else
        datetimes.push(_mergeDateTime(dates[0], times[0], tz))

    if times.block?
      datetimes.block = times.block
      if datetimes[0]
        date = moment.tz(datetimes[0], tz)
      while datetimes.length isnt 0
        datetimes.pop()
      if mode is 'in'
        mode = 'none'
    else if datetimes.length is 2
      if mode is 'out'
        Logger.error 'An out-punch cannot be a range', new Error(original)
        return
      if datetimes[1].isBefore datetimes[0]
        datetimes[1] = datetimes[1].add(1, 'days')
      elapsed = _calculateElapsed datetimes[0], datetimes[1], mode, user
      if mode is 'in'
        mode = 'none'

    [projects, command] = _parseProjects command
    notes = command.trim()

    punch = new Punch(mode, datetimes, projects, notes)
    punch.date = datetimes[0] || date || moment.tz(tz)
    punch.timezone = tz
    if elapsed
      punch.elapsed = elapsed
    punch
  
  @parseRaw: (user, row, projects = []) ->
    if not user
      return
    else if not row
      return
    else if not row.save or not row.del
      return
    headers = HEADERS.rawdata
    date = moment.tz(row[headers.today], 'MM/DD/YYYY', TIMEZONE)

    # UUID sanity check
    if row[headers.id].length != 36
      Logger.debug "#{row[headers.id]} is not a valid UUID, changing to valid UUID"
      row[headers.id] = uuid.v1()
      Organization.spreadsheet.saveRow(row)

    if row[headers.project1] is 'vacation' or
       row[headers.project1] is 'sick' or
       row[headers.project1] is 'unpaid'
      mode = row[headers.project1]
    else if row[headers.in] and not row[headers.out]
      mode = 'in'
    else if row[headers.out] and row[headers.totalTime]
      mode = 'out'
    else
      mode = 'none'
    datetimes = []
    tz = user.timetable.timezone.name
{'fraction_non_alphanumeric': 0.12193103448275862, 'fraction_numerical': 0.012827586206896552, 'mean_word_length': 2.623688155922039, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, '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': '4704225', 'n_tokens_mistral': 2407, 'n_tokens_neox': 2263, 'n_words': 654}