text:
"""
Module for manipulating records of hours worked

Record
  Object that simulates a single record of work done
RecordMalFormedException
  Wrapped exception used and required, internally, by the Record class

After importing, set (optional):
  ROOT_DIR - default: '.'
  HOURS_DIR - default: './hours'
"""

### IMPORTS ############################################################################################

import calendar
import datetime as dt
import os

### RUNNING AS MAIN ####################################################################################

if __name__ == "__main__":
  print("Import class.")
  print("Exiting...")
  exit(1)

### MODULE VARS ########################################################################################

ROOT_DIR = "."
""" Allows the module to reference the root project directory
Recommended to manually set after importing """

HOURS_DIR = os.path.join(ROOT_DIR, "hours")
""" Where the module will save recorded-hours files
Recommended to manually set after importing """

PENDING_CHAR = "***"
""" Used as a placeholder for the end time and duration in a record
It is replaced (within the record) when the next record is created or when the end time is supplied """

PERIOD_END = 25
""" Day of the month on which the pay period ends """

########################################################################################################
#### CLASS DEF START ###################################################################################
########################################################################################################

class Record:
  """
  Object that simulates a single record of work done
  """

  def __init__(self, string):
    """ PUBLIC - Default Constructor
    Parses a properly-formatted string into a Record object
    :param string: <str> to parse - must be in correct format

    Format: "name|startDate start|endDate end|duration|label|billable|emergency|notes(|durationLocked)"
    Example: "test|2017-01-12 12:00|2017-01-12 16:30|4.5|TS|N|N|test0|False"

    Optional field 'durationLocked': will default to False
    Invalid string: throws a RecordMalformedException
    """
    try:
      #######################################################

      elems = string.split('|')
      start_DT = elems[1].split(" ")
      end_DT = elems[2].split(" ")

      #######################################################

      self.name = elems[0]
      """ <str> : username of the person working """

      self.date = validateDate(start_DT[0])
      """ <datetime.date> : date of work done """

      #######################################################

      self.fstart = start_DT[1]
      """ <str> : "HH:MM"-formatted start time for work done """

      self.start = parseTime(self.fstart)
      """ <str> : "HHMM"-formatted start time for work done """

      self.fend = end_DT[1]
      """ <str> : "HH:MM"-formatted end time for work done """

      self.end = parseTime(self.fend)
      """ <str> : "HHMM"-formatted end time for work done """

      #######################################################

      self.duration = elems[3]
      """ <str> : number of hours, in decimal, of work done """

      self.label = elems[4]
      """ <str> : label of project/entity for which work was done """

      self.billable = elems[5]
      """ <str/char> : 'Y'|'N' flag for whether work is billable """

      self.emergency = elems[6]
      """ <str/char> : 'Y'|'N' flag for whether work was emergent """

      self.notes = elems[7]
      """ <str> : description of what work was done """

      #######################################################

      self.durationLocked = False
      """ <bool> : if True, prevents future changes to the duration of the work done
      This is set to True by manually entering a duration for the work
      It is only visible in the Record object or in the hidden version of the log file
      """

      if (len(elems) == 9) and (elems[8] == "True"):
        self.durationLocked = True

      #######################################################

    except Exception:
      raise RecordMalformedException("ERROR - INVALID __init__ STRING : " + string)

  ### DURATION METHODS ###################################################################################
  ########################################################################################################

  def setDuration(self, duration):
    """
    Sets the duration to a supplied value
    :param duration: <float|(str)> new duration value (casts to float)
    """
    # TODO: decide if I want to change this to @duration.setter and add @property functions
    self.duration = float(duration)

  def calculateAndSetDuration(self):
    """
    Calculates the duration from own start and end times, then sets the duration
    """
    # TODO: decide if I want to change up getDuration (module func) in relation to setDuration (class func)
    self.setDuration(getDuration(self.start, self.end))

  def modifyDuration(self, amount):
    """
    Modifies the existing duration by a specified amount, iff not durationLocked
    :param amount: <float|(str)> number of hours, in decimal, by which to shift the duration (casts to float)
    """
    if not self.durationLocked:
      # get the duration
      d = float(self.duration)

      # add the amount (supplying a negative amount will subtract from the duration)
      d += float(amount)

      # set modified duration
      self.duration = str(d)

  ### TIME METHODS #######################################################################################
  ########################################################################################################

  def isPending(self):
    """
    True iff an end time has not been supplied
    If pending, self.end and self.duration have been set as PENDING_CHAR
    :return: <bool> pending status of record
    """
    return self.end == PENDING_CHAR

  def setStart(self, time):
    """
    Sets the start time while ensuring correct parsing/formatting
    :param time: <str> value to set as start time
    """
    time = str(time)

    # parse time for start field (format "HHMM")
    parsed = parseTime(time)

    # format parsed time for fstart (formatted start) field (format "HH:MM")
    formatted = formatTime(parsed)

    self.start = parsed
    self.fstart = formatted

  def setEnd(self, time):
    """
    Sets the end time while ensuring correct parsing/formatting
    :param time: <str> value to set as start time
    """
    time = str(time)

    # parse time for start field (format "HHMM")
    parsed = parseTime(time)

    # format parsed time for fstart (formatted start) field (format "HH:MM")
    formatted = formatTime(parsed)

    self.end = parsed
    self.fend = formatted

  def modifyStart(self, amount):
    """
    Modify the start time and duration by the supplied amount
    :param amount: <float|(str)> number of hours, in decimal, by which to shift the start and duration (casts to float)
    """
    # get start time in minutes
    start = convertTimeToMinutes(self.start)

    # convert amount into minutes and add to start time
    newStart = float(start) + (float(amount) * 60)

    # TODO: double check that the int casting is needed
    # set start to newStart value (converted back into a string)
    self.setStart(convertMinutesToTime(int(newStart)))

    # modify the duration by subtracting the amount added to the start time
    self.modifyDuration(-float(amount))

  def modifyEnd(self, amount):
    """
    Modify the end time and duration by the supplied amount
    :param amount: <float|(str)> number of hours, in decimal, by which to shift the end and duration (casts to float)
    """
    # get the end time in minutes
    end = convertTimeToMinutes(self.end)

    # convert amount into minutes and add to end time
    newEnd = float(end) + (float(amount) * 60)

    # TODO: double check that the int casting is needed
    # set end to newEnd value (converted back into a string)
    self.setEnd(convertMinutesToTime(int(newEnd)))

    # modify the duration by adding the amount added to the end time
    self.modifyDuration(float(amount))

  def modifyTimes(self, amount):
    """
    Modify both the start and end times by the supplied amount
    This shifts the entire time frame and does *not* change the duration
    :param amount: <float|(str)> number of hours, in decimal, by which to shift the start and end times(casts to float)
    """
    self.modifyStart(amount)
    self.modifyEnd(amount)

  ### TO_STRING METHODS ##################################################################################
  ########################################################################################################

  def __str__(self):
    """ Default to_string - called via str(record)
    This format contains durationLocked and is intended for writing to a hidden file
    :return: <str> formatted record data
    """
    return "{emailFormat}|{durationLocked}".format(
      emailFormat=self.emailFormat(), durationLocked=self.durationLocked)

  def emailFormat(self):
    """ Secondary to_string
    This format doesn't contain durationLocked and is intended for emailing/submitting to payroll
    :return: <str> formatted record data
    """
    return "{name}|{startDate} {start}|{endDate} {end}|{duration}|{label}|{billable}|{emergency}|{notes}".format(
      name=self.name,
      startDate=self.date, start=self.fstart,
      endDate=self.date, end=self.fend,
      duration=self.duration,
      label=self.label,
      billable=self.billable, emergency=self.emergency,
      notes=self.notes)

########################################################################################################
#### CLASS DEF END #####################################################################################
########################################################################################################

#

########################################################################################################
#### HELPER CLASS DEF START ############################################################################
########################################################################################################

class RecordMalformedException(Exception):
  """
  Wrapped exception used and required, internally, by the Record class
  """
  pass

########################################################################################################
#### HELPER CLASS DEF END ##############################################################################
########################################################################################################

#
#
#
#
#
#
#
#
#

########################################################################################################
#### MODULE METHODS START ##############################################################################
########################################################################################################

### GENERATOR METHODS ##################################################################################
########################################################################################################

def generateFileName(name, date):
  """
  Produces a filename for a specific day of records
  :param name: <str> name of user
  :param date: <str>|<datetime.date> date of records
  :return: <str> filename with format "YYYY-MM-DD-name"
  """
  # get current date if supplied date is ""
  date = validateDate(date)

  # "-" between date and name in filename
  filename = "{0}-{1}".format(str(date), name)

  # return filename
  return os.path.join(HOURS_DIR, filename)

def generateHiddenFileName(name, date):
  """
  Produces a hidden filename for a specific day of records
    The hidden file contains an extra piece of info (durationLocked) for each record that day
  :param name: <str> name of user
  :param date: <str>|<datetime.date> date of records
  :return: <str> filename with format ".YYYY-MM-DD-name"
  """
  # get current date if supplied date is ""
  date = validateDate(date)

  # "." prepended and "-" between date and name in filename
  filename = ".{0}-{1}".format(str(date), name)

  # return filename: uses hidden version of the file, since it contains extra info (durationLocked)
  return os.path.join(HOURS_DIR, filename)

### IO METHODS #########################################################################################
########################################################################################################

def readRecords(name, date):
  """
  Attempts to read records from a file corresponding to the name and date supplied
  :param name: <str> name of user
  :param date: <str|datetime.date> date of records
  :return: <list[str] or []> unparsed list of records as strings
  """

  # uses hidden version of the file, since it contains extra info (durationLocked)
  fileName = generateHiddenFileName(name, date)

  if os.path.exists(fileName):
    try:
      with open(fileName, 'r') as f:
        records = f.read().split('\n')
        return records

    except IOError:
      pass

  return []

def writeRecords(name, date, records):
  """
  Writes a list of records to a file with a name generated from name and date
  :param name: <str> name of user
  :param date: <str|datetime.date> date of records
  :param records: <list[recorder.Record]> records to write to file
  """

  fileName = generateFileName(name, date)

  # used to store extra information (durationLocked)
  hiddenFileName = generateHiddenFileName(name, date)

  # will contain joined records and be written to files
  res, hiddenRes = "", ""

  #######################################################

  # join the records into strings
  for r in records:
    res += r.emailFormat() + "\n"
    hiddenRes += str(r) + "\n"

  #######################################################

  # write strings to files
  try:
    with open(fileName, 'w') as f:
      f.write(res)

    with open(hiddenFileName, 'w') as f:
      f.write(hiddenRes)

  except IOError:
    pass

def deleteRecords(name, date):
  """
  Uses a system call to delete the normal and hidden files corresponding to a name and date
  :param name: <str> name of user
  :param date: <str|datetime.date> date of records
  """

  fileName = generateFileName(name, date)

  # used to store extra information (durationLocked)
  hiddenFileName = generateHiddenFileName(name, date)

  # system calls to delete both normal and hidden file
  os.system("rm -f {}".format(fileName))
  os.system("rm -f {}".format(hiddenFileName))

### SUBTOTAL & TOTAL METHODS ###########################################################################
########################################################################################################

def getSubtotalForDay(name, date):
  """ PUBLIC
  Adds up the hours worked on a specific day by a user
  :param name: <str> name of user
  :param date: <str>|<datetime.date> date of records
  :return: <float> total hours worked during the day
  """
  records = parseRecordsFromFile(name, validateDate(date))
  subtotal = countSubtotal(records)
  return subtotal

def getTotalForPayPeriod(name, date):
  """ PUBLIC
  Adds up subtotals of each record in the pay period (adjusted for the 25th of the month)
  :param name: <str> name of user
  :param date: <str>|<datetime.date> date within the pay period
  :return: <float> total hours worked during the pay period
  """

  date = validateDate(date)
  total = 0.0

  """ NOTE:
  beforeCutoff<Month,Year> is the part of the pay period that occurs between the 26th and the end of the month
    in actuality, this is kind of erroneous naming, since all the counted days happen after the cutoff
    (by nature of being within the pay period);

  afterCutoff<Month,Year> is the part of the pay period that occurs between the 1st and the 25th of the month
  """

  if date.day <= PERIOD_END:
    # DATE IS BEFORE THE 25th, meaning the cutoff happened in the previous month
    beforeCutoffMonth = date.month - 1 if date.month > 1 else 12
    beforeCutoffYear = date.year - 1 if beforeCutoffMonth == 12 else date.year

  else:
    # DATE IS AFTER THE 25th, meaning the cutoff happened in this month
    beforeCutoffMonth = date.month
    beforeCutoffYear = date.year

  # get the last day of the month
  beforeCutoffMonthEnd = calendar.monthrange(beforeCutoffYear, beforeCutoffMonth)[1]

  # these statements reference beforeCutoff<Month,Year> and not date to consolidate the following logic
  afterCutoffMonth = beforeCutoffMonth + 1 if beforeCutoffMonth < 12 else 1
  afterCutoffYear = beforeCutoffYear + 1 if afterCutoffMonth == 1 else beforeCutoffYear

  # GET TOTAL FOR DAYS IN RANGE : 26th - LAST DAY OF MONTH
  for day in range(PERIOD_END + 1, beforeCutoffMonthEnd + 1):
    beforeCutoffDate = dt.date(year=beforeCutoffYear, month=beforeCutoffMonth, day=day)
    total += getSubtotalForDay(name, beforeCutoffDate)
    # print("DATE : {} -- SUBTOTAL : {} -- TOTAL : {}".format(beforeCutoffDate, getSubtotalForDay(name, beforeCutoffDate), total))

  # GET TOTAL FOR DAYS IN RANGE : 1st - 25th
  for day in range(1, PERIOD_END + 1):
    afterCutoffDate = dt.date(year=afterCutoffYear, month=afterCutoffMonth, day=day)
    total += getSubtotalForDay(name, afterCutoffDate)
    # print("DATE : {} -- SUBTOTAL : {} -- TOTAL : {}".format(afterCutoffDate, getSubtotalForDay(name, afterCutoffDate), total))

  return total

def getTotalForPayWeek(name, date):
  date = validateDate(date)
  total = 0.0

  '''
  For use if you want to go off of the "techsquare" week (Saturday through friday).
  tsWeek = ["Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
  tsWeekDay = tsWeek.index(tsWeek[date.weekday() - 5])
  weekStart = date - dt.timedelta(days=tsWeekDay)
  weekEnd = date + dt.timedelta(days=6 - tsWeekDay)
  '''

  weekStart = date - dt.timedelta(days=date.weekday())
  weekDates = []

  for day in range(7):
    weekDates.append(weekStart + dt.timedelta(day))

  for dates in weekDates:
    total += getSubtotalForDay(name, dates)

  return total

def getPayPeriodMonth(date):
  """ PUBLIC
  Produces the datetime.date string representation of the pay period month
  :param date: <str|datetime.date> date within the pay period
  :return: <str> corresponding to the pay period month (ex: "2016-12-26" --> "Jan")
  """
  date = validateDate(date)

  if date.day <= PERIOD_END:
    month_int = date.month
  else:
    # if past the cutoff, increment the month and wrap around if necessary
    month_int = date.month + 1 if date.month < 12 else 1

  # correcting for year is not necessary because only the month string is returned
  # likewise, the day value is not needed, so hard-coding as 1 prevents day-out-of-range error
  date = dt.date(date.year, month_int, 1)

  # get the str name for the month
  return date.strftime("%b")

def countSubtotal(records):
  """ PRIVATE
  Sums the durations of a list of recorder.Record objects
  Will parse record strings into objects
  :param records: <list[recorder.Record|str]>
  :return: <float> subtotal
  """
  subtotal = 0.0

  for each in records:

    if type(each) is str:
      subtotal += float(Record(each).duration)

    elif isRecord(each) and not each.isPending():
      subtotal += float(each.duration)

  return subtotal

### PARSING METHODS ####################################################################################
########################################################################################################

def parseRecords(raw_records):
  """ PRIVATE
  Parses string records into recorder.Record objects
  :param raw_records: <list[str]>
  :return: <list[recorder.Record]>
  """
  # filter out empty records
  records = filter(None, raw_records)

  # return list mapped to Record objects
  return [Record(r) for r in records]

def parseRecordsFromFile(name, date):
  """ PUBLIC
  Reads records from a file and parses the strings into a list of recorder.Record objects
  :param name: <str> name of user
  :param date: <str|datetime.date> date of records
  :return: <list[recorder.Record]> parsed records for the date and user
  """
  # read in records
  raw_records = readRecords(name, date)

  # return parsed Record objects
  return parseRecords(raw_records)

def parseRecordFromHTML(request):
  """ PUBLIC
  Parses the data from an HTML form into a recorder.Record object
  :param request: <bottle.request> contains HTML form data
  :return: <recorder.Record> parsed object
  """

  name = request.forms.get('name').strip().lower()

  start = parseTime(request.forms.get('start'))
  end = parseTime(request.forms.get('end'))
  ###
  duration = request.forms.get('duration').strip()
  ### billable/emergency are each either 'Y' or 'N'
  billable = request.forms.get('billable')
  emergency = request.forms.get('emergency')
  ###
  label = request.forms.get('label').strip().upper()
  # filters out "|" char to not confuse the later parsing (better solution would be a check in the HTML)
  notes = request.forms.get('notes').strip().translate(None, '|')

  #######################################################

  # duration locked is only present in the hidden file, since it is extra data for each record
  durationLocked = False

  # if a duration is entered
  if duration:
    # lock it to prevent changing
    durationLocked = True

  # if there is no duration and the end time was provided
  elif start and end:
    # calculate the duration
    duration = getDuration(start, end)

  # if end is not supplied
  else:
    # replace duration with PENDING_CHAR
    duration = PENDING_CHAR

  #######################################################

  # restore colon in start time
  start = formatTime(start)

  # if end is supplied
  if end:
    # restore the colon
    end = formatTime(end)

  # if not supplied
  else:
    # set as PENDING_CHAR
    end = PENDING_CHAR

  #######################################################

  # get the date cookie or default to current date ; save as str
  date = str(validateDate(request.get_cookie("hours-app-date")))

  #######################################################

  # format the string that will be supplied to the Record constructor
  record_string = \
      "{name}|{startDate} {start}|{endDate} {end}|{duration}|{label}|{billable}|{emergency}|{notes}|{durationLocked}" \
      .format(
        name=name,
        startDate=date, start=start,
        endDate=date, end=end,
        duration=duration,
        label=label,
        billable=billable, emergency=emergency,
        notes=notes,
        durationLocked=durationLocked)

  return Record(record_string)

### TIME METHODS #######################################################################################
########################################################################################################

def parseTime(t):
  """
  Conforms a time string to format "HHMM"
    Removes ':' and fills with leading '0'
  :param t: <str> time to parse
  :return: <str> time in format "HHMM"
  """

  if t:
    # return if pending
    if t == PENDING_CHAR:
      return t

    # removes colon and adds leading '0' if missing
    return str(t.strip()).translate(None, ':').zfill(4)

  # if not supplied, return empty string
  return ""

def formatTime(t):
  """
  Conforms a time string to format "HH:MM"
    calls parseTime(t) beforehand
  :param t: <str> time to format
  :return: <str> time in format "HH:MM"
  """
  # ensures time is parsed correctly
  p = parseTime(t)

  # adds a colon between hours and minutes
  return "{HH}:{MM}".format(HH=p[:2], MM=p[2:])

def convertTimeToMinutes(t):
  """
  Converts a time string into an int representing the number of minutes since 00:00
  :param t: <str|(int)> time to convert to minutes (will accept but simply return an int)
  :return: <int> number of minutes since 00:00; 0 if the end time is pending
  """
  # checks for not present time
  if t == PENDING_CHAR:
    #TODO: ensure that changing this from `return None` to `return 0` doesn't break anything
    return 0

  # if it is an int, it has already been processed, so return
  # ex: called from getDuration()
  if type(t) is int:
    return t

  # ensures it is parsed to "HHMM"
  p = parseTime(t)

  # returns number of minutes (HH*60 + MM)
  return (int(p[:2]) * 60) + int(p[2:])

def convertMinutesToTime(minutes):
  """
  Converts a number of minutes since 00:00 into a time string
  :param minutes: <int|(str)> number of minutes (will cast to int)
  :return: <str> time string in the format "HHMM"
  """
  # ensures int type
  i = int(minutes)

  # gets hours through integer division
  hours = str(i / 60).zfill(2)

  # gets minutes through modulus
  minutes = str(i % 60).zfill(2)

  # return ("HHMM")
  return hours + minutes

def getDuration(start, end):
  """
  Calculate a duration using start and end times
  :param start: <str> starting time string
  :param end: <str> ending time string
  :return: <float or 0.0> number of hours between start and end
  """
  # get number of minutes from start time
  start = convertTimeToMinutes(start)

  # get number of minutes from end time
  end = convertTimeToMinutes(end)

  if start and end:
    # return number of hours as float (x.xx)
    return float((end - start) / float(60))

  # if end == PENDING_CHAR
  return 0.0

# TODO: decide whether to keep this and figure out how overloading is done best in Python
# def getDuration(record):
#   """
#   Calculate a duration from a record's data
#   :param record: <recorder.Record>
#   :return: <float> either the record's duration or the value calculated from its start and end times
#   """
#
#   if record.duration:
#     return float(record.duration)
#
#   start = convertTimeToMinutes(record.start)
#   end = convertTimeToMinutes(record.end)
#
#   return getDuration(start, end)

def roundTime(t):
  """
  Rounds the passed in time to the nearest 15-minute mark
  :param t: <str|datetime.time> time to round
  :return: <str> rounded time in the format "HHMM"
  """

  if type(t) is dt.time:

    hours = t.hour
    minutes = t.minute

  else:

    t = formatTime(t)
    hours, minutes = (int(i) for i in t.split(':'))

  #######################################################

  # calculate the number of quarter-hour units (rounded down) the minutes equal
  quarters = minutes / 15

  # calculate how far from the next quarter-hour mark the minutes are
  remainder = minutes % 15

  #######################################################

  # if the time is at least 7 minutes into the current quarter-hour, increment quarters
  if remainder > 7:
    quarters += 1

  # if there are over three quarters, the hour has been passed: add an hour and reset quarters to 0
  if quarters > 3:
    hours += 1
    quarters = 0

  #######################################################

  # return ("HHMM") now rounded to the quarter-hour
  return "{HH}{MM}".format(HH=str(hours).zfill(2), MM=str(quarters * 15).zfill(2))

def getCurrentRoundedTime():
  """
  Rounds the current time to the nearest 15-minute mark
  :return: <str> rounded time in the format "HHMM"
  """
  # get current time ; round it to 15-minute mark
  return roundTime(dt.datetime.now().time())

### RECORD METHODS #####################################################################################
########################################################################################################

def getPrevRecord(records, index):
  """
  Attempts to get the chronologically previous record
  :param records: <list[recorder.Record|(str)]> list of records (type doesn't matter)
  :param index: <int> index value of starting record (index - 1 should be the previous record)
  :return: <recorder.Record|(str) or None> previous record from list (returns whatever the list element type is)
  """
  try:
    # if the previous index is a valid index
    if index - 1 >= 0:
      # return the previous record
      return records[index - 1]

  except IndexError:
    pass

  # if returning the prev record was unsuccessful, return None
  return None

def getNextRecord(records, index):
  """
  Attempts to get the chronologically next record
  :param records: <list[recorder.Record|(str)]> list of records (type doesn't matter)
  :param index: <int> index value of starting record (index + 1 should be the next record)
  :return: <recorder.Record|(str) or None> next record from list (returns whatever the list element type is)
  """
  try:
    # if the next index is a valid index
    if index + 1 < len(records):
      # return the next record
      return records[index + 1]

  except IndexError:
    pass

  # if returning the prev record was unsuccessful, return None
  return None

def adjustAdjacentRecords(records, index):
  """
  Checks if a specific record overlaps with adjacent records and adjusts adjacent start/end times accordingly
  :param records: <list[recorder.Record]> list of records
  :param index: <int> index of the record to use as the base for adjusting
  """
  # if the records list is empty, print error statement and return from function
  # TODO: decide if this print statement is ok or what to do with it
  if not records:
    print("ERROR: empty records list passed into adjustAdjacentRecords()")
    return

  #######################################################

  # get the newly-inserted / base record
  base_record = records[index]

  # get the previous record if it exists
  prev_record = getPrevRecord(records, index)

  # get the next record if it exists
  next_record = getNextRecord(records, index)

  #######################################################
  """ FUNCTION: ADJUSTS THE PREVIOUS RECORD'S END TIME
  the base record *FINISHES* the previous record
  visually:
    previous: [START][PENDING --> END]
    base: [START][PENDING|END]
  """
  if prev_record and isRecord(prev_record):
    # if the previous record's end time has not been supplied
    if prev_record.duration == PENDING_CHAR:
      # set the previous record's end time to be the new record's start time
      prev_record.setEnd(base_record.start)

  #######################################################
  """ FUNCTION: SHIFTS NEXT RECORD'S START TIME (IF PARTIAL RECORD)
  the base record *SHIFTS* the next record forward to match its end time
  visually:
    base: [START][END]
    next: [START --> MODIFIED START][PENDING|END]
  """
  if next_record and isRecord(next_record):
    # if (the next record's end time has not been supplied) and (the base record has an end time)
    if (next_record.duration == PENDING_CHAR) and (base_record.end != PENDING_CHAR):
      # supply the next record's start time using the new record's end time
      next_record.setStart(base_record.end)

    # TODO: FIX THE REST OF THIS METHOD
    # TODO: make sure for all : isRecord(r)
    """
    I don't think I changed any logic, but I need to decide how this will work
      specifically, if two records in a row can have pending end times
    Pseudocode out the steps
      1)  set previous end time to base start time
      2)  if next is pending and base isn't: set next start time to base end time
      3?) if base is pending: set base end to next start
      4?) ?
      5?) ?
    Create an as-simple-as-possible overview of the method at the top
    """
    ####### REQUIRED TAG IN HTML END TIME INPUT BYPASSES THIS CODE ######

    # FUNCTION: SETS NEW RECORD'S END TIME (REDUNDANT)

    # NOTE: this case seems to work, but the HTML requires the end time in this case, so this isn't currently executed

    """
    if the next record doesn't have a supplied end time, the new record MUST have an end time (required by HTML input)
    """
    # if (a next record exists) and (the new record has a pending duration)
    if base_record.duration == PENDING_CHAR:
      # set the end time of the new record to be the next record's start time
      base_record.setEnd(next_record.start)

      #######

  #######################################################

  # after ensuring the previous record's end time is set

  if prev_record:

    # calculate the previous record's duration using its start and end times
    prev_record.duration = getDuration(prev_record.start, prev_record.end)

    # update the record in the list
    records[index - 1] = prev_record

    # calculate overlap : new_start - prev_end : if overlap => negative duration
    # if the new start time is less than the previous end time: adjustment needed
    overlap = getDuration(prev_record.end, base_record.start)

    # if there was overlap
    if overlap < 0:
      # modify the prev_end time by subtracting the overlap duration
      prev_record.modifyEnd(overlap)

  #######################################################

  # if the next record exists, the new record has been ensured to be complete (can't have two pending records)

  if next_record:

    # calculate the new record's duration using its start and end times
    base_record.duration = getDuration(base_record.start, base_record.end)

    # update the record in the list
    records[index] = base_record

    # calculate overlap : next_start - new_end : if overlap => negative duration
    # if the next record's start is less than the new record's end: adjustment needed
    overlap = getDuration(base_record.end, next_record.start)

    # if there was overlap
    if overlap < 0:
      # modify next_start time by subtracting overlap duration
      next_record.modifyStart(-overlap)

def checkIfValid(records, record, index):
  """
  Checks if a new record is temporally sound with itself and in relation to adjacent records
    i.e. checks that a record's start comes before its end
      and checks that a record doesn't overlap an entire adjacent record
  :param records: <list[recorder.Record]> list of records not including the one passed in
  :param record: <recorder.Record> single record to check if it fits validly in the record list
  :param index: <int> index where the new record is trying to be placed
  :return: <bool> returns True only if record fits between (existing) adjacent records
  """
  # get records to check positioning of the new record
  prevRecord = nextRecord = None

  # for checking the relationship with self and the adjacent records
  prevValid = nextValid = selfValid = False

  ################################################

  if not record or not isRecord(record):
    return False

  if records:
    prevRecord = getPrevRecord(records, index)
    nextRecord = getNextRecord(records, index)

  ################################################

  # either there is no previous record
  if not prevRecord:
    prevValid = True

  # or the new start is greater than the previous start
  elif isRecord(prevRecord):
    prevValid = record.start > prevRecord.start

  ################################################

  # either there is no nextRecord record
  if not nextRecord:
    nextValid = True

  # or the new end is less than the nextRecord end
  # (implied) if record is pending, the nextRecord record must not exist
  elif not record.isPending() and isRecord(nextRecord):
    nextValid = record.end < nextRecord.end

  ################################################

  # if a record is pending, it is valid with itself
  if record.isPending():
    selfValid = True

  # else, the start must come before the end
  else:
    selfValid = record.start < record.end

  ################################################

  # true iff all checks are passed
  return prevValid and nextValid and selfValid

  # TODO: maybe return a second var that's a list of reasons why the record was invalid

def validateDate(d):
  """
  Normalizes dates as datetime.date objects
  :param d: <str|(datetime.date)> to convert to datetime.date (will return unchanged a passed-in datetime.date object)
  :return: <datetime.date> converted date if supplied else the current date
  """
  # TODO: does this belong in this section? Helper methods section?
  # if datetime.date
  if type(d) is dt.date:
    return d

  # if str and not ''
  elif (type(d) is str) and d:
    try:
      # could throw ValueError
      # could throw a TypeError
      year, month, day = [int(x) for x in d.split("-")]

      return dt.date(year=year, month=month, day=day)

    except (ValueError, TypeError):
      pass

  # if invalid date supplied, return current date
  return dt.date.today()

def isRecord(r):
  return r.__class__.__name__ == "Record"

########################################################################################################
########################################################################################################
#### MODULE METHODS END ################################################################################


Are these a definite no no, or can they be worn and then thrown? I wear cheap shoes to work sometimes but am concerned they look cheap!!
It's really down to personal choice and comfort, more money doesn't always mean better. So if your happy with cheaper shoes then that's fine personally I have a whole range of cheap to mid to high end to suit my needs. It's really down to personal choice.
I would add that sometimes it's worth spending more on one pair that last year's than less on several over the year.
I have cheap shoes that I love too. If they make you happy and they're suitable for your needs, then go for it!
Agreed! I have shoes in every price range. Wear what you like. Don't worry about the price tag.
I donno about flats but I have some cheap heels I wear if I know there gonna get ruined at like a club or something and I just don't care about them but I swear my feet wind up smelling way more when I wear cheap heels so I'd guess its the same for cheap pumps?


There are currently no upcoming soccer listings scheduled on NTV+ Sport Online.
Are we missing any soccer listings for NTV+ Sport Online? If so, please let us know.
NTV+ Sport Online is a Russian live streaming channel available on the NTV Plus satellite platform.


NGTC welcomes visitors, especially prospective students, because the best way to understand the spirit of North Georgia Technical College and its commitment to providing quality student-focused occupational programs is to join us on campus and take a tour. See first-hand how NGTC has produced alumni from throughout the Southeast who have excelled in their professions.
Current students lead tours at each of the three campuses from August through April providing information about the history of NGTC, answering questions, and adding unique viewpoints based on their individual experience at the College.
In the event of inclement weather, please check the calendar, or call regarding a scheduled tour time.
Please provide a Mobile Number where we can reach you on the day of the tour.
I am interested in learning about the Dormitory/Residence Hall.
The Clarkesville Campus of North Georgia Technical College is located in a mountain setting off Georgia Highway 197 one and one-half miles north of Clarkesville, the county seat of Habersham County. It is situated on 339 picturesque acres, 40 of which comprise the state-of-the-art campus.
Once you arrive on campus, meet at the Clegg Center (Building A) at least 15 minutes prior to start time and tell the receptionist you are there for a tour. You will then be introduced to a member of our friendly staff who is committed to making your visit a great experience.
The Blairsville Campus is a state-of-the-art facility with a dramatic view of the beautiful Blue Ridge Mountains. It sits on a knoll overlooking the 25 acres located along the Zell Miller Parkway just outside the town of Blairsville.
Please arrive at least 15 minutes prior to start time and meet with our friendly staff at the Main Office who are committed to making your visit a great experience.
The Currahee Campus of NGTC is a 45,000+ square foot state-of-the-art facility located at the Haystone Brady Industrial Park in southern Stephens County.
Our courses are offered in a wide variety of venues ranging from traditional classroom to those that make use of advancing technology.


Am I biting off more than I can chew? I Probably am!
Whelp, Only JUST realized that if I use a 48x48 grid in Photoshop... I can just build my own maps in Photoshop... >.< FREEDOM!
Yes, Indeed it is. I personally use GIMP.
Well I've always used Photoshop because my dad has a license because we use it for Photography... so I just use what I have as I know its a good enough software and an alternative.
AND, there are more contests coming.
It sure will! Keep at it, buddy!
Just implemented the time system that I wanted! All is going well at the moment! Even if I don't always work on it and it takes a long time. It should be worth it!
, why? well because you can put their review in your trailer, it gives a sense of priority and help boost confidence from gamer to developer.


Megan Rudne of Colchester is an art education major at Southern Connecticut State University with a 3.80 GPA. Rudne is a member of the President's Sustainable Climate Committee, the Environmental Futurists Club and received an official citation from the City of New Haven Board of Alderman in 2008. She has been feeding homeless people on the New Haven Green for the last several years and is on the board of directors of the Compassionate Living Project. She was the recipient of the Sylvia Leggiero Spino Memorial Scholarship from the SCSU Alumni Association in both 2007 and 2008. Rudne has been employed as a student worker in the Office of Judicial Affairs and as a resident advisor in the Office of Residence Life. She plans to pursue a master of science degree in special education with a specialization in autism spectrum disorders to help exceptional children express themselves through art.


The tennis team started its singles Spring season, kicking it off with a tournament in Westwood on Feb. 9.
Tennis officially starts as early as Aug. 1 with doubles, but with tennis Coaches Marie Bruce and Jordan Ramey coaching different sports during the fall, tennis got a later start than other schools.
For Bruce coaching tennis was an automatic yes. With past experiences in tennis Bruce was very enthusiastic about teaching others how to play.
Tennis isn't just about learning the rules and how to hit a ball with a racket.
Most of the players who joined the team followed Bruce from volleyball.
"I really like Coach Bruce and I enjoy playing tennis," sophomore and varsity volleyball play Ally Felty said.
Because most players came from volleyball relationships were already built between the team members.
Players got the chance to choose what team they wanted to be on, Freshman or JV, through a questionnaire sent out by Bruce. Bruce then picked the best players from each team to play in tournaments.


text:
class Digitizer;
class G4UIcmdWithAnInteger;
class G4UIcmdWithADouble;
class G4UIcmdWithADoubleAndUnit;

class DigitizerMessenger: public G4UImessenger {
	public:
		DigitizerMessenger(Digitizer*);
		~DigitizerMessenger();

		virtual void SetNewValue(G4UIcommand*, G4String);

	private:
		Digitizer* fDigitizer;
		G4UIdirectory* fDigiSetupDir;
		G4UIcmdWithAnInteger* fThresholdCmd;
		G4UIcmdWithAnInteger* fNoiseCmd;
		G4UIcmdWithADouble* fBiasCmd;
		G4UIcmdWithADouble* fDeplCmd;
		G4UIcmdWithADouble* fTemperatureCmd;
		G4UIcmdWithAnInteger* fDriftDirectionCmd;
		G4UIcmdWithADoubleAndUnit* fInitChargeCloudCmd;
		G4UIcmdWithADouble* fCorrChargeCloudCmd;
		G4UIcmdWithAnInteger* fTriggerCmd;
		G4UIcmdWithAnInteger* fTypeCmd;
		G4UIcmdWithAnInteger* fRepCmd;
};

#endif

redpajama_set_name: RedPajamaGithub


Things are good at the Parks household... Payton's fever is finally under control. She started looking a little perky last night & slept the whole night without waking up with high fever! Thank you Lord! The fighting has returned between Presley and her, so that is a good sign that she is feeling better!!! She even ate breakfast this morning AND ate some soup & grilled cheese for lunch! She is dying that she has missed 3 days of school. If all goes well today, she can return to school tomorrow. It's so nice to see that sparkle in her eyes again... it's been a long 5 days!
Good for y'all. It is so nice to have well kids. If I can only keep mine better at the same time. We need to set up a sleepover time with your two girls. Walker will not quit talking about it.
Okay, this picture is BEAUTIFUL! I love it...I also love it that everyone is getting better!!!


text:
The sale of electric bulbs on different days of a week is shown below :
Observe the pictograph and answer the following questions :
(a) How many bulbs were sold on Friday?
(b) On which day were the maximum number of bulbs sold?
(c) On which of the days same number of bulbs were sold?
(d) On which of the days minimum number of bulbs were sold?
(e) If one big carton can hold 9 bulbs. How many cartons were needed in the given week?
We use the concept of data handling to answer the given questions.
(a) On Friday, a total of 14 bulbs were sold.
(b) On Sunday, a total of 18 bulbs were sold.
Hence, the maximum number of bulbs was sold on Sunday.
(c) 8 bulbs are sold on Wednesday and Saturday.
Hence, on both Wednesday and Saturday, an equal number of bulbs were sold.
(d) 8 bulbs are sold on Wednesday and Saturday.
Hence, the Minimum number of bulbs was sold on Wednesday and Saturday.
(e) A total of 86 bulbs were sold in the given week.
⇒ 12 + 16 + 8 + 10 + 14 + 8 + 18 = 86
Since one big carton can hold 9 bulbs, we would require
⇒ 86/9 ≈ 10 cartons
∴ 10 cartons were needed in the given week.
NCERT Solutions for Class 6 Maths Chapter 9 Exercise 9.1 Question 6
The sale of electric bulbs on different days of a week is shown below: Observe the pictograph and answer the following questions: (a) How many bulbs were sold on Friday? (b) On which day were the maximum number of bulbs sold? (c) On which of the day's same number of bulbs were sold? (d) On which of the day's minimum number of bulbs were sold? (e) If one big carton can hold 9 bulbs. How many cartons were needed in the given week?
Using the concept of data handling, we can conclude that (a) 14 bulbs were sold on Friday (b) the maximum number of bulbs sold was on Sunday (c) the same number of bulbs were sold on Wednesday and Saturday (d) the minimum number of bulbs were sold on Wednesday and Saturday and (e) 10 cartons were needed in the given week to hold 86 bulbs.
In A Mathematics Test The Following Marks Were Obtained By 40 Students Arrange These Marks In A Table Using Tally Marks
Following Is The Choice Of Sweets Of 30 Students Of Class Vi Ladoo Barfi Ladoo Jalebi Ladoo Rasgulla Jalebi Ladoo Barfi Rasgulla Ladoo Jalebi Jalebi Rasgulla Ladoo Rasgulla Jalebi
Catherine Threw A Dice 40 Times And Noted The Number Appearing Each Time As Shown Below
Following Pictograph Shows The Number Of Tractors In Five Villages Observe The Pictograph And Answer The Following Questions I Which Village Has The Minimum Number Of Tractors

redpajama_set_name: RedPajamaCommonCrawl


Welcome to our last episode of the Back to Basics series. In our last two episodes, we spoke about the Why when it comes to real estate investing and the How. On today's session, Kirk and Emily speak about the basics of financing your initial real estate deals.
Are there multiple ways to finance a real estate deal. OF Course.
The reality, however, is that when you are just starting out your options may be a little more limited because of your lack of a portfolio. Therefore, understanding that there are a few different avenues that you can take as a Rookie.
Tune in to find out how house hacking can be a viable option for you and obtaining your first deal. Not only that, Kirk and Emily discuss both the Pros and Cons of buying, living in and turning a property into a rental and buying a traditional investment property right off the bat.
I love your back to basic series idea – too many websites / podcasts keep searching for new topics. After a while the topics are esoteric and just more complicated than they need to be. Since I bet you want people to actually take action, keeping it simple and revisiting the fundamentals are key!
Thanks Brian! I appreciate your feedback and totally agree. It never hurts to revisit the basics and make sure we are giving actionable advice to people getting started.


Bad Customer Service… For the Right People!
Home » Bad Customer Service… For the Right People!
Flew from Orlando to New Orleans today. Right after I got on, a couple with two little girls gets on. The husband sits the girls down in the front row and, par their custom, the SWA flight attendant informed the family that the front row has more leg room, yes, but all bags have to go in overhead AND there were no tray tables. As soon as the flight attendant gets this out of his mouth, the wife turns and snarls at the husband, "You idiot!" Being a good husband, he ignores her. The wife sits down with her purse on her lap and the flight attendant says, "Did I say just some bags in the overhead compartment? No! ALL bags in the overhead compartment!" I was a bit surprised at his saucy talk to her, but he got the last laugh. When she spits at the flight attendant and says, "I am NOT putting my purse up there!" He smiles, points to an entire plane that is virtually empty. Even my blind self can pick up on the smug, "Gotcha!" coming off of him.
I'm always a big fan of customer service, but when people are as ignorant to others as this woman was, she deserves to be put in her place. Thanks for another smile, SWA!


text:
The Run of the Mill
Exploring Carrollton's Textile Past
Click Here for the Carrollton Walking Trail Brochure: Download
Map of the Run of the Mill Brochure
Run of the Mill Brochure Highlights:
Sign Markers:
Run of the Mill Panel:
For many southerners, the history of the region's textile past is a very personal and familial story. During the late-1800s to mid-1900s, Carrollton experienced the ebb and flow of the industrializing South from several vantage points. Carroll County's farmers grew cotton as a cash crop then carted their harvests into town for market. Cotton and hosiery mills processed the cotton into textile products while creating new domestic and labor settings for many rural folk. The rail lines connected Carrollton to a larger southern network and transported the city's textile goods. This industry powered economic development in Carrollton, producing immense change and growth during the twentieth century. We invite you to discover this history through the Carrollton Spur of the West Georgia Textile Heritage Trail. The brochure includes a trail map with signage locations and additional sites to see along the way.
Introductory and Cotton Sign:
In the early 1900s, cotton was king in Carrollton. Even during industrialization, the city maintained much of its farming tradition. Historic Adamson Square was the site of busy cotton markets where farmers would sell their crops to textile factories and merchants. The introductory sign of the Carrollton trail is located in the southeast quadrant of Adamson Square.
The Knitted Road:
Carrollton's textile industry diversified during the 1920s and 30s as new hosiery mills began sharing Bradley Street with the older warehouses vital to the local cotton market. Located between Adamson Square and the Train Depot, Bradley Street became an important industrial sector, adding finished goods to the textile products made in the city. The Bradley Street sign is located in the parking lot of the Southeastern Quilt and Textile Museum.
The Bustling Depot:
The train depot proved instrumental in the growth of the local industry by connecting Carrollton to a larger network of southern cities and towns. From the mid-1870s through the early-1900s, this depot served as both a transportation hub and a cotton goods warehouse. Today, the Norfolk Southern Corporation's freight lines continue to pass by the depot. The trail sign is located at the train depot, on the southern end of Bradley Street.
The Textile Industry Comes to Carrollton:
Cotton mills built the New South. Large cotton mills and mill villages, like the ones here, were sites in which many farm families adapted to new industrial settings and denser living conditions. The Mandeville Mills Historic District contains the surviving mill no.1 factory and mill village, with historic mill homes and street layouts that have changed little over the past century. The trail sign is located on Lovvorn Road, in front of the factory's old smoke stack.
The Road to Industrialism:
Three of the Mandeville Mills' founders, and early catalysts of change in Carrollton, called this portion of Maple Street home. Textile mill owners played a complex role in the industrializing South. Today, little is known of how the Mandeville Mills' owners exactly used their positions and resources, and visitors are encouraged to draw their own conclusions. The trail sign at the Maple Street railroad crossing tells this story.
1. The Cotton Farmer: Newnan Street
Carrollton's late "sculptor-in-residence," Henry Setter, completed The Cotton Farmer in 1997 with the hope of educating citizens about the region's agricultural past. In his mid-sixties, Setter carved the cotton bale out of a 3,000-pound block of granite which had to be craned into City Hall Park.
2. Southeastern Quilt & Textile Museum: 306 Bradley Street
Located in the old Carroll Mills warehouse, the Southeastern Quilt and Textile Museum promotes the preservation of quilting and local textile heritage. Along with rotating exhibits and displays of prizewinning quilts, the museum provides additional quilting programs and classes taught by instructors in their areas of expertise. Visit southeasternquiltmuseum.com for more information.
3. Lawler Hosiery Mill: Bradley Street
The Lawler Hosiery Mill opened on the ground floor of Carroll Mills in 1927. In 1934, operations moved to the historic building you see today. Like other mills on Bradley Street, Lawler made finished products, primarily socks. The passing of the 1994 North American Free Trade Agreement (NAFTA) ended Lawler's operations a year later, but, the historic building continues to serve Carrollton as loft apartments.
4. Carroll Mills: 202 Bradley Street
In 1924, Carroll Mills became the first of many Bradley Street textile operations. Unlike the Mandeville Mills, Carrollton's first textile factory, Carroll Mills produced finished products such as shoe strings and cotton meat packaging. As diversification of the textile industry grew on Bradley Street, Carroll Mills housed newer operations, like Lawler Hosiery Mill and Caroline Mills, until these enterprises could construct their own buildings
5. Railroad Spur Lines: 455 Bradley Street
You may have noticed short rail lines branching from the main line here at the depot. These shorter rails, called spur lines, were important for textile businesses like the Mandeville Mills. By connecting textile operations to main routes, spur lines allowed mills to receive cotton and ship their products.
6. H.O. Lovvorn Home: 113 East College Street, Bowdon, Ga
Reared in nearby Bowdon, Georgia, Henry Lovvorn served as the Mandeville Mills' first secretary and treasurer. A successful business man, Lovvorn was also a local civic, political, and industrial leader. He built this elaborate Greek Revival-style home right outside the mill village in 1907.
7. Maple Street School:
The first Maple Street School was constructed on this site in 1917, but was destroyed by fire in 1947. Mill children could not enroll here without paying tuition because the village rested just outside city limits. This fee would have been difficult for mill families to afford. The tuition problem was a reason the mill owners constructed the Westview Grammar School in the mill village around the same time. In 1922, the school board voted to allow mill children into the Maple Street School.
8. BlueWater Ropes: 209 Lovvorn Rd
BlueWater Ropes began as a hobby to supplement the founder's caving activities. Now an international company, it is one of two operational textile-related mills in Carrollton. The company represents several generations of textile production, reaching back to one of the Mandeville Mill's founders, Leroy Mandeville.
9. First Home Constructed in Mill Village:
Built in 1900, the home on the corner of Lovvorn Road and Burson Avenue was the site of Carrollton's first mill house. The house-type is called a "saltbox house" because the pitch of the roof resembles a New England saltbox house when viewed from its side. This particular mill house is common in northern states, and is found in other southern textile towns. Salt-box mill houses migrated to the region with the New England textile industry.
10. Former Mill Church:
Constructed for mill workers around 1900, this building was once called Westview Church. In the early 1900s, the building housed a union church where different denominations would rotate services weekly.
11. Mandeville Mill no. 2 (Water Tower):
In 2006, a fire destroyed the original site of Mandeville Mill no. 2, leaving the old water tower as one of the sole standing structures. Carrollton is still rich with textile related sites, but, this surviving tower continues to remind us of the importance of historic preservation and the memory which may be lost when cultural resources are not managed and protected.
12. 506 Maple Street:
This odd-shaped building tells us about Carrollton's economy over the past century. Constructed around 1911, the building served as a cotton and guano warehouse, replacing older warehouses at this point along the rail line. In the 1950s, Maryon Hosiery Mill moved here. Now, local businesses occupy it, one of which still deals in textiles.
13. Joseph Aycock House: 408 Maple Street
Joseph Aycock, the first manager of the Mandeville Mills, is a significant figure in the industrialization of Carrollton. Considered by contemporaries as a man of many talents, he is the architect, designer, and engineer of most buildings within the Mandeville Mills Historic District. He also designed many of Carrollton's other notable buildings and the city's first modern cotton ginnery. His pyramidal house may not look as impressive as Mandeville's or Lovvorn's homes, but it was built roughly 40 years earlier around 1862 and is much larger and ornate than similar pyramidal homes in the mill village.
14. Leroy Mandeville Mansion: 401 Maple Street
Born in Carrollton to New England parents, Leroy Mandeville was very active in several areas of the city's development around the turn-of-the-twentieth-century. He was a merchant, banker, and served as the Mandeville Mill's first president. Mandeville was also active in local government and helped bring the 4th District A&M School, now the site of the University of West Georgia, to the city. Around 1900, he built this ornate Queen Anne home, a very popular house-style during the period. It is said to have been the first house in the city to carry running water, electricity, and a telephone line.
Email the Trail at wgtht@westga.edu or call UWG Center for Public History at 678-839-6141 for more information.


Jonathan Marx won a 2004 Webby Award for best website in Spirituality, using the concept of Continuous Engagement.
1993 Cable Positive Award – first year awarded, for AIDS community programming, Viacom Cable San Francisco, Senior Vice President Jonathan Marx.
1992 Corporate Leadership Award, San Francisco AIDS Foundation, Viacom Cable San Francisco, Senior Vice President Jonathan Marx. Developed Continuous Engagement using television, bill stuffers, events.


text:
Q: Why would Guid.NewGuid() be generating an empty guid? I have a Guid.NewGuid() call that is creating an Empty Guid.
What would cause such a problem and how can I fix it?
Edit: The code:
<WebMethod()> _
Public Function CreateRow(rowValue As String) as String
    Dim rowPointer As Guid = System.Guid.NewGuid()
    Dim rowPointerValue As String = rowPointer.ToString()

    Try
        Dim result as Integer = SqlHelper.ExecuteNonQuery(ConnectionString, "Sproc_Name", rowValue, rowPointer)

        Return result
    Catch ex as Exception
        Throw ex
    End Try
End Function

Edit: Turns out that rowPointer was originally being passed to the SqlHelper and not rowPointerValue - This of course is passed as empty, as pointed out in the answers.  Changing it to rowPointerValue/rowPointer.ToString() fixed the problem.

A: This is an old problem in VB.NET. It is only the debug visualizer that is broken.
http://www.thesoftwaredevotional.com/2008/12/guid-visualizer-broken-in-vbnet.html

A: I had the same thing. Debugging of Guid.NeGuid() was showing that it's empty. Calling .ToString() fixed the situation.

A: I tested this code in VS2008 and the results are not what I expected.  It seems that the new guid is not created until the toString method is called.  After stepping through the code rowPointerValue does hold a string representation of the guid.
It seems to be using defferred execution?

A: I've only experiened this problem in VB.NET and only while debugging.  Thanks 48494, for that info.

A: Try this
Dim g As New Guid();

Dim whereDoYouWantToSeeIt As String = g.ToString();

redpajama_set_name: RedPajamaStackExchange


The Coalition for Energy Efficient Comminution (CEEC) is an international, not-for-profit company, entirely funded by sponsorship from the minerals industry. Its mission is to share energy efficient, productive mining processes to help reduce costs, lower footprint and improve shareholder value.
Announcing a sponsorship agreement with Eriez, CEEC CEO Ms Alison Keogh said she was pleased to welcome the US-based company to the CEEC team.
"Eriez brings an exciting option to mineral processing circuits with its innovative HydroFloat™ technology, which has potential to significantly cut costs and boost processing efficiency," she said.
Alison stated "Eriez highlights the potential to add significant value through flotation of coarser material. When successfully commercialised at full scale, this will dramatically reduce costs by lowering use of energy, water and other resources per unit."
Eriez Australia Managing Director Mr. Jaisen Kohmuench said his company was proud to partner with a true collaborator like CEEC.
"We were familiar with CEEC's global initiatives and were introduced to CEEC by colleagues in North America. We wanted to help support CEEC's work and to share our key learnings with the mining industry, so we're excited to come on board as a sponsor," he stated.
Jaisen pointed out a recent study by Dr Jan Miller at the University of Utah has shown that the HydroFloat™ can recover copper ore particles as coarse as 1mm with a mineral surface expression as low as 1%. By increasing the size of ore particles from 20 to 80 microns, for example, the energy required per tonne drops from 20-30 kWh/t to less than 7 kWh/t.
Ms Keogh explained that comminution is the process in which solid materials are reduced in size by crushing, grinding and other processes. Comminution is an important step in minerals processing and can consume 50% of a mining operation's costs. Flotation is a process used after comminution to separate and extract valuable minerals. This traditionally needs very fine particles to work.
"Commercialisation of technologies, such as the HydroFloat™, has the potential to transform the way operations manage energy, water and other resources," she said.


Visidraft, an augmented reality software for iOS devices, has gained some limelight in the pages of Architect Magazine.
Israel Medina, VP of Business Development for Visidraft, a new AR (augmented reality) software company we first learned about at AIA Atlanta, this year, contacted Architosh to share with us the news that Visidraft is being featured in Architect Magazine.
Visidraft is an augmented reality software app for your iPad or iOS device, and while the company did not have an official booth at AIA Atlanta, they did through a party in conjunction of sorts with the Nemetschek Vectorworks folks, which many people did attend.
At the AIA Atlanta Visidraft party those entering the party were given an iPad device and led on a four to five stop AR tour through a bar and outside deck party space wherein each participant could evaluate the use of Visidraft in action.
01 – Visidraft recently was featured in Architect Magazine, as Augmented Reality (AR) technology begins to gain more limelight in the AEC space.
The latest version of Visidraft is now at 2.1.1 (since 10 July 2015) and has improved tracking, 1-finger pan and move model support, 2-finger to rotate and move up/down, and 3-finger to adjust camera height, tap on the model to measure distance, et cetera.
Visidraft is compatible with AutoCAD, Revit, SketchUp, 3ds max, Vectorworks and ArchiCAD.
To learn more about Visidraft visit them online here.


text:
2020-01-17T18:29:41Z 2020-01-17T18:29:41Z The state's office of disciplinary counsel announced it is seeking to suspend the license of civil attorney Kent Mawhinney who is charged in connection to the murder case of Jennifer Dulos.
2020-01-17T17:51:35Z 2020-01-17T17:51:35Z There is a potential for a snowstorm in the forecast this weekend, News 12 meteorologists say.
Police: Bullet holes, weapons, makeshift bunker found in Stamford home of convicted felon
2020-01-17T22:34:08Z 2020-01-17T22:34:08Z Police say they found various weapons in the Stamford home of a convicted felon.
2020-01-17T20:17:33Z 2020-01-17T20:17:41Z Student loan debt has crossed the $1.6 trillion mark, more than double what it was in 2010.
2020-01-17T19:51:29Z 2020-01-17T19:51:29Z A family displaced by the earthquakes devastating Puerto Rico escaped to safety in Stratford.
2020-01-17T20:31:41Z 2020-01-17T20:31:41Z Police say a disgruntled customer assaulted a Trumbull mall food court worker and a group of people caused more than $1,000 in damage all stemming from the portion size of a food order.
2020-01-17T21:45:46Z 2020-01-17T21:45:46Z A Bridgeport man with autism is the subject of a new NFL film that debuted on national TV this week.
2020-01-17T17:19:32Z 2020-01-17T17:19:32Z White has been nominated for 21 Primetime Emmy Awards, one Grammy Award and in December 2013, she became the Guinness World Record holder for longest TV career for a female entertainer.
Google's parent company joins $1 trillion market cap club
2020-01-17T16:47:36Z 2020-01-17T16:47:47Z Here's the latest business and technology headlines courtesy of Cheddar.
2020-01-17T15:51:30Z 2020-01-17T15:50:02Z This week, Chef Ian Hock of Jesup Hall in Westport shows Tina Redwine how to make American dishes including sustainable meats and salads.
Univision 41 News Brief: Mujer baleada en Brooklyn durante intento de robo
Una mujer fue baleada en Brooklyn durante un intento de robo.
Fire officials: Fire breaks out on roof of Bridgeport Hospital
2020-01-17T12:41:35Z 2020-01-17T12:41:41Z A fire broke out on the roof of Bridgeport Hospital, officials say.
Officials: Man slashed multiple times in Bridgeport refused to cooperate with police
2020-01-17T15:29:15Z 2020-01-17T15:29:15Z A man was slashed several times, and police say he is being uncooperative in their investigation.
The Download: My Audio Pet
2020-01-17T12:08:40Z 2020-01-17T12:08:53Z The My Audio Pet are tiny Bluetooth speakers that pack a serious audio punch. But the adorable little characters do more than just play music - they can tell stories to children as well.
Poll: National Hot Buttered Rum Day
2020-01-17T09:44:18Z 2020-01-17T09:44:18Z Hot buttered rum is especially favored during the fall and winter months! So let's celebrate today with a drink!
Univision 41 News Brief for Jan. 16, 2020
Here are the morning top stories for Univision on Jan. 16, 2020.
Police: Man injured in Bridgeport shooting
2020-01-16T03:20:01Z 2020-01-16T03:20:01Z A man was hospitalized after he was shot at the Trumbull Gardens housing complex Wednesday.
Power & PoliticsMore>>
Republican Brian Farnen wins 132nd district special election in Fairfield
Updated: Tuesday, January 14 2020 10:02 PM EST2020-01-15 03:02:28 GMT
Republican Brian Farnen won the special election for the 132nd district in Fairfield Tuesday.
132nd District hopefuls campaign at Fairfield train station ahead of special election
Updated: Monday, January 13 2020 1:49 PM EST2020-01-13 18:49:51 GMT
132nd District hopefuls campaigned outside Fairfield train station Monday ahead of tomorrow's special election.
Fairfield candidates hit campaign trail ahead of special election for state House seat
Updated: Sunday, January 12 2020 6:54 PM EST2020-01-12 23:54:58 GMT
Fairfield candidates made the final push to secure votes Sunday in the special election race for the state House seat in the 132nd Assembly District.
Power & Politics - Toll plan latest, cell service on trains and more
Updated: Saturday, January 11 2020 7:26 PM EST2020-01-12 00:26:34 GMT
Democrats say they may have enough votes to pass a tolling plan. Plus, the trains may be slow -- but your phone is about to get a lot faster on Metro-North.
House approves measure to restrain Trump's actions on Iran
Updated: Thursday, January 9 2020 6:30 PM EST2020-01-09 23:30:11 GMT
The House passed the measure, 224-194, with just three Republicans voting in support. Eight Democrats opposed the measure.
The measure will "protect American lives and values" by limiting Trump's military actions, Pelosi said. "The administration must de-escalate and must prevent further violence.''
Noticias Univision 41More>>
Univision 41 News Brief: ICE arresta abuelo que se recuperaba de una operación
ICE arresta abuelo que se recuperaba de una operación. Mujer muere atropellada por camión de basura
Univision 41 News Brief: Al menos 11 personas resultaron desplazadas por incendio en Mount Hope
Al menos once personas resultaron desplazadas por el incendio en sus apartamentos de Mount Hope, El Bronx.
Univision 41 News Brief: Casero muere tras incidente con inquilino en Queens
Gobernador de NY llega a Puerto Rico.
CrimeMore>>
A man was slashed several times, and police say he is being uncooperative in their investigation.
Fotis Dulos, attorney ask for probable cause hearing
Fotis Dulos and his attorney Norm Pattis want a hearing to determine whether police had probable cause to arrest him for the murder of his estranged wife Jennifer Dulos.
Authorities: Juvenile serial sex offender arrested in Stamford assaults
A juvenile serial sex offender was arrested in Maryland in November and again in Stamford last month, according to authorities.
The 17-year-old, who was not named, is accused of raping two women in Stamford. He was apprehended with the help of the U.S. Marshal's Office.
THE :30More>>
MEET THE HULK! North Carolina dog gives birth to a green puppy
The puppy is perfectly healthy, but his fur was discolored in utero.
FIERCE FELINE: A cat takes on THREE coyotes and lives!
Max's owner is now considering building a "catio" to protect him from predators when he goes outside.
Mom buys digital billboards across Colorado Springs to try to find her son's killer
Thomas Anthony Faircloth was found dead in a parking lot in November. His death was ruled a homicide.
Group of kids return AirPods to NFL player who dropped them on Missouri street
The teens tweeted the Chiefs defensive tackle and got in contact with him within minutes.
Florida mom gives birth to TWO sets of twin boys in one year
She gave birth in March, and then again on Dec. 27.
OffbeatMore>>
3 not-so-little pigs escape on Sunrise Highway, rescued by police
Three no-so-little pigs that escaped from a trailer Friday morning on Sunrise Highway were rescued by Suffolk police.
Scarsdale teen's internship at NASA leads to planet discovery
A Scarsdale teenager went way beyond during his internship with NASA last summer.
Burger King offers free whoppers for residents who dealt with 'Joker Stairs' tourism
Updated: Tuesday, January 7 2020 7:53 AM EST2020-01-07 12:53:34 GMT
Burger King is giving the Bronx a reward for dealing with an influx of people thanks to Joaquin Phoenix's film "Joker."
Robbinsville police use funny road signs to help keep the public safe
Updated: Friday, January 3 2020 8:00 PM EST2020-01-04 01:00:24 GMT
Some humorous digital signs in a Mercer County town are going viral in an effort to keep the town safe.
Teed off: Residents near golf course rally against neighbor's large net
A group of Brielle residents who live near a golf course says that they are annoyed by a large net a neighbor installed to catch golf balls.
Chopper 12More>>
Chopper 12 over Brooklyn Bridge march against anti-Semitism
Chopper 12 was over the scene as demonstrators marched over the Brooklyn Bridge in a show of solidarity against anti-Semitism on Sunday, Jan. 5, 2020.
Chopper 12 tours the historical defenses around NYC
Chopper 12 over scene of Manorville brush fire response
Chopper 12 was over the scene of the emergency response to a brush fire in Manorville on Sunday, July 7.
Chopper video over Ridgefield house explosion
Updated: Monday, June 17 2019 4:00 PM EDT2019-06-17 20:00:55 GMT
An explosion leveled a Ridgefield home Monday morning, sending one man to the hospital.
Chopper 12 over scene of Mattituck small plane crash
Chopper 12 was over the scene of a small plane crash in Mattituck on Saturday, June 8. Police say two people were killed in the crash.
Hometown HeroMore>>
Hometown Hero Information
Do you know a Hometown Hero? Call, write, or email News 12 Connecticut and that person could be featured on News 12 Connecticut's Hometown Hero segment every Wednesday.
Hometown Hero photos
Updated: Monday, March 25 2019 2:27 PM EDT2019-03-25 18:27:01 GMT
Olsen is the board chair of Fairfield County's Community Foundation and chairs its executive committee. As chair, she is involved with the foundation's annual Giving Day.
Hometown Hero photo gallery
Photos of Connecticut's "Hometown Heroes"
Hometown Hero: Joyce Olson
Joyce Olson of Norwalk has been volunteering at the Westport Center for Senior Activities for almost 13 years.
Hometown Hero: Dr. Dana Wade
Wade is the CEO of Monitor My Health Inc., a Bridgeport nonprofit that offers lifestyle change programs to prevent diabetes and heart disease. They recently received a $25,000 federal matching grant from the CDC and state Department of Health.
Hometown Hero: Diane Votto
Diane Votto, a Milford military veteran is helping fellow military members this holiday season. She is a member of the Dream Team Moms, a group that makes pillowcases for combat soldiers and stuffs stockings with personal care items.
U.S. & World NewsMore>>
Posted: Friday, January 17 2020 12:56 AM EST2020-01-17 05:56:34 GMT
(AP Photo/ Evan Vucci). In this Jan. 14, 2020, photo, President Donald Trump arrives at UW-Milwaukee Panther Arena to speak at a campaign rally in Milwaukee. Trump's surrogates are fanning out across the country as part of an aggressive effort to stret...
President Donald Trump's surrogates are fanning out across the country as part of an aggressive effort to stretch his appeal beyond the base of working-class white voters who propelled him to victory in 2016.
President Donald Trump's legal team will include former Harvard University law professor Alan Dershowitz and Ken Starr, the former independent counsel who led the Whitewater investigation into President Bill Clinton.
'Days of God': A look at Iran's mounting crises
(Office of the Iranian Supreme Leader via AP). In this picture released by the official website of the office of the Iranian supreme leader, worshippers chant slogans during Friday prayers ceremony, as a banner show Iranian Revolutionary Guard Gen. Qas...
Iran's supreme leader says his nation is living through "days of God.
(AP Photo/Santiago Billy). Honduran migrants walking in a group stop before Guatemalan police near Agua Caliente, Guatemala, Thursday, Jan. 16, 2020, on the border with Honduras. Less-organized migrants, tighter immigration control by Guatemalan author...
United States officials are crediting tough measures taken over the past year and cooperation from regional governments for sharply reducing the number of Central American migrants who responded to a call for a new...
United States officials are crediting tough measures taken over the past year and cooperation from regional governments for sharply reducing the number of Central American migrants who responded to a call for a new caravan.
Iran's top leader strikes defiant tone amid month of turmoil
(Office of the Iranian Supreme Leader via AP, File). FILE-In this file photo released on May 22, 2019 by the official website of the office of the Iranian supreme leader, Supreme Leader Ayatollah Ali Khamenei speaks to a group of students in Tehran, Ir...
Iran's supreme leader will deliver a Friday sermon in Tehran for the first time since 2012.
BusinessBusinessMore>>
Toyota will stop making its Tacoma small pickup in San Antonio next year as it shifts production to Mexico.
For some major US shippers, 2019 ended on a sour note
(AP Photo/Eric Risberg, File). FILE - In this May 14, 2019 file photo, a Cosco Shipping container ship passes the Golden Gate Bridge in San Francisco bound for the Port of Oakland. For major shipping companies dealing with trade wars and a slowing glob...
For major shipping companies dealing with trade wars and a slowing global economy, conditions appear to have deteriorated as 2019 came to a close.
China welcomes US deal, says 'core concerns' must be met
Posted: Thursday, January 16 2020 5:46 AM EST2020-01-16 10:46:04 GMT
(AP Photo/Ng Han Guan). Investors monitor stock prices at a brokerage in Beijing Thursday, Jan. 16, 2020. Share prices are mixed in moderate trading in Asia after the U.S. and China signed a preliminary trade agreement that investors hope will bring be...
China has welcomed an interim trade deal with Washington and said the two sides need to address each other's "core concerns.
(AP Photo/Nati Harnik, File). FILE - In this Dec. 12, 2019, file photo workers process chickens at the Lincoln Premium Poultry plant, Costco Wholesale's dedicated poultry supplier, in Fremont, Neb. On Friday, Jan. 17, 2020, the Federal Reserve reports ...
US industrial production fell 0.3% in December, as unseasonably warm month limited the need for heating from utilities.
(Photo by Chris Pizzello/Invision/AP, File). FILE - In this April 3, 2019, file photo, Alan Horn, chairman of The Walt Disney Studios, speaks underneath poster images for 20th Century Fox films during the Walt Disney Studios Motion Pictures presentatio...
Published reports say Disney is dropping the word "Fox" from movie studios it acquired as part of last year's $71 billion purchase of Fox's entertainment business.
Quick LinksQuick LinksMore>>
Submit a News Tip to News 12
Do you have a story idea or breaking news tip to share with News 12?