text: '''
  *** Districtr Json Reader ***
  By Ryan Gomez, Feb. 22, 2021
  
  To leverage Districtr's utility to load, ammend and tabulate statistics on a variety
  of polticial districts, this file outlines a Python object that wraps around the 
  maps generated by Districtr, allowing for downloading, manipulating and saving these
  boundary files in in Python. 
  
  Districtr uses its own JSON format, outlined in AboutDistrictrJSON.md. The DistrictrJson
  object models this JSON format allowing for manipulation. 
  
  -> For now, this object is set to map *Louisiana* state-wide districts. This is an issue
  if we wanted to plot state-wide maps for other states or smaller, say, parish or city
  only juristictions. Thus, when these maps are loaded back into Districtr, these smaller
  districts are compared with State statistics totals. In the future, we'll find a way
  to limit the extent of juristictions. 
  
  To that end, we define a *DistrictrJson* object which is in essence, a Python dictionary
  with utility functions.
  
  The utility function Ordinal produces a string with numbers and their English Ordinal
  Suffixes, 1st, 2nd, 3rd, 4th, etc.
  '''
  
  # Dictionaries of Boilerplates for blank Louisiana-based Districtr JSON files.
              
  import json
  import LA_Settings as LA
  
  def Ordinal(n):
      '''
          Utility function returns ordinal string.
          Takes: Integer
          Returns: String with ordinal, "1st," "2nd," "3rd," "4th," etc.
      '''
      return "%d%s" % (n, 'tsnrhtdd'[(n//10%10!=1)*(n%10<4)*n%10::4])
  
  class DistrictrJson:
      '''
          Class that encapsulates Distrctr JSON format for manipulation.
          Essentially a dictionary with utility functions. Refer to 
          AboutDistrictrJSON.md for more information. 
          
          For LOUISIANA files only.
      '''
      def __init__(self, title, unit, unitsplural, oldfile=None,
                         ordinalnames=False, customNames=False):
          '''    
              Constructor takes a Districtr JSON style file or can produce
              an empty Object with Louisiana boilerplate information. 
          
              Requries problem title, unit and plural units name.
              May take JSON file and contains a setting for ordinal names
              and may accept custom district names.
          
              Instance variables include self.data, which contains all information
              as dict and other settings. Removes units.columnSets to save space.
          '''
          self._data = dict()       
          self._unit = unit
          self._ordinalnames = ordinalnames
          self._customNames = customNames
          
          newData = {}
          if oldfile:
              with open(oldfile) as f:
                  newData = json.load(f)   
              try: del newData["units"]["columnSets"] # Deletes columnSets
              except: pass
          else:
              newData.update(LA.IDCOLUMN)
              newData.update(LA.PLACE)
              newData.update(LA.PLACEID)
              newData["problem"] = {}
              newData["assignment"] = {}
              
          self._data = newData
          print(self._data)
          self.setProblem(title, unitsplural)
      
      def getAssignment(self):
          '''
              Get method for current assignment as dictionary.
              -> Returns a copy or reference to same object?
          '''
          return self._data["assignment"]
      
      def setAssignment(self, newAssignments):
          '''
              Takes dictionary of new Precinct-District assignments.
              No error checking! Updates Problem and Parts.
          '''
          self._data["assignment"] = newAssignments
          self.setProblem()
          self.setParts()
          return
          
      def setProblem(self, newTitle="", newUnitsPlural = ""):
          if newTitle: self._data["problem"]["name"] = newTitle
          if newUnitsPlural: self._data["problem"]["pluralNoun"] = newUnitsPlural
          self._data["problem"]["numberOfParts"]=self.findPartsNumber()
          return 
  
      def findPartsNumber(self):
          '''
              Finds number of unique assignemnts in Assignment section. 
              Takes: Self, Returns: Integer of unique assignments
          '''
          return len(set(self._data["assignment"].values()))
      
      def setParts(self, ordinal=False, custom=None):
          '''
              Updates parts based on number of assignments. 
              Parts are a list of dicts that carries the format...
              "parts": [{"id", "displayNumber", "name": "District 1"},...]
              
              Takes ordinal and custom settings. Supercedes constructor, self, settings.
          '''                
          
          if not ordinal: ordinal = self._ordinalnames
          else: self._ordinalnames = ordinal
          
          if not custom: custom = self._customNames
          else: self._customNames = custom
          
          newParts = []
          numberOfParts = self.findPartsNumber()
          
          for part in range(numberOfParts):
              partDict = {}
              partDict["id"] = part
              partDict["displayNumber"] = part+1
              if (ordinal):
                  partDict["name"] = f"{Ordinal(part+1)} {self._unit}"
              elif (custom):
                  partDict["name"] = custom[part]
              else:
                  partDict["name"] = f"{self._unit} {part+1}"
              newParts.append(partDict)
          self._data["parts"] = newParts
      
      def write(self, outfile):
          '''
              Writes new JSONraw file that can be read into the Districtr app. 
              Only writes what's necessary for reading:
                  "Assignment," "Problem," "Parts," "Place," "PlaceID," "Units," and "Problem"
                  
                  Should but does not yet check for Problem and Parts agreement. 
                  
                  See AboutDistrictrJSON.md
          '''
          datawrite = dict()
          datawrite["assignment"] = self._data["assignment"]
          datawrite["problem"] = self._data["problem"]
          datawrite["parts"] = self._data["parts"]
          datawrite["place"] = self._data["place"]
          datawrite["placeId"] = self._data["placeId"]
          datawrite["units"] = self._data["units"]        
          datawrite["problem"] = self._data["problem"]
      
          with open(outfile, 'w') as outf:
              json.dump(datawrite, outf)
  
  
  
  if __name__ == "__main__":
      #Write Tests Here
      pass