Skip to content

Conversation

@hjaensch7
Copy link
Contributor

@hjaensch7 hjaensch7 commented Apr 21, 2022

  • csv builders for projects, forests, and project updates
  • data backing airtable
  • PALS integration

@hjaensch7 hjaensch7 self-assigned this Apr 28, 2022
@hjaensch7 hjaensch7 force-pushed the hj/csv-builder branch 3 times, most recently from 07b5182 to e5ec7d8 Compare May 1, 2022 01:36
Copy link

@maloneya maloneya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to merge, none of my concerns are blocking.

tl;dr

  1. some suggestions for errors and logging
  2. some organizational suggestions with our type and schema definitions
  3. some organizational suggestions for csv utilities
  4. some style suggestions to improve readability

Additionally i think that writeProjectsCsv is currently super confusing, i don't really understand how the dedupe and leftoverForests things is supposed to work. There is likely a much simpler way of accomplishing this transformation

i would also suggest that we just store the CSVs in Drive not Github

filePath := "data/pals.csv"
err := writePALSCsv(config.PalsDataFile, filePath)
if err != nil {
log.WithFields(log.Fields{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth considering where in the program you want to log your errors.

if by default you log an error every time you if err != nil you end up with pretty polluted log stream

my suggestion would be to have each abstraction decorate the error with its relevant context, i.e.

return fmt.Errorf("Unable to write CSV %w", err) 

and allow the top level controller to do the logging


}

type PalsEntry struct {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be in Types.go?

}

func writePALSCsv(original_path string, path string) error {
// 26 - 43

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean?


func writePALSCsv(original_path string, path string) error {
// 26 - 43
purposes := map[string]string{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are these local variables to the function? perhaps should be a global constant, or also stored in types.go?

//open original file
f, err := os.Open(original_path)
if err != nil {
log.Fatal(err)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit pick: log.Fatal(fmt.Errorf("writePalstoCSV open call err: %w", err)) would make it easier to pinpoint where in the program the error came from


// build column headers
writer := csv.NewWriter(csvFile)
writer.Write([]string{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any way we can leverage the existing headers for this and just skip the activity?

// TODO(hank)
func writeForestCsv(forests []Forest, path string) error {
// open file
csvFile, err := os.Create(path)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a general call out that there are multiple places in the code base that deal with the file and csv apis, we could make a single utility that was just

func writeCSV(header []string. rows string[][]) error

and then each transform is just responsible for produce the new rows, but doesn't care about the CSV details

project.Description,
project.WebLink,
project.Location,
project.Location[10:],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

??? should probably explain in a comment

}

func getDocsAsString(project ProjectUpdate) string {
allDocs, _ := json.Marshal(project.ProjectDocuments)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error?

Comment on lines +141 to +176
// dedupe forests first!!

// remove all but one project update
forestMap := make(map[int]Forest)
forestIdsToRemove := []int{}
// inital map
for i, forest := range forests {
// check if forest in map
if _, ok := forestMap[forest.Id]; !ok {
forestMap[forest.Id] = forest
forestIdsToRemove = append(forestIdsToRemove, i)
}
}

// build list of leftover forests TODO clean up
leftoverForests := []Forest{}
for i, forest := range forests {
shouldBeRemoved := false
for _, index := range forestIdsToRemove {
if index == i {
shouldBeRemoved = true
}
}
if !shouldBeRemoved {
leftoverForests = append(leftoverForests, forest)
}
}

// iterate through leftovers and add states
for _, forest := range leftoverForests {
if forestInMap, ok := forestMap[forest.Id]; ok {
forestInMap.State = forestInMap.State + ", " + forest.State
forestMap[forest.Id] = forestInMap
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we make a separate Transform type function that captures all this business logic?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would also say that this code is pretty hard to follow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants