implement transaction.go:FromURLs with a FALSE solution and modify unittest to show that while the unittest is passing it is a FALSE solution

main
bel 2023-10-15 13:46:25 -06:00
parent 6e17faf4b1
commit 9e5bfc48bd
4 changed files with 746 additions and 5 deletions

View File

@ -15,18 +15,21 @@ type Analyzer struct {
// Add adds unique transactions to Analyzer. // Add adds unique transactions to Analyzer.
func (anz *Analyzer) Add(transactions Transactions) int { func (anz *Analyzer) Add(transactions Transactions) int {
added := 0
for i := range transactions { for i := range transactions {
dupe := false dupe := false
for j := range anz.transactions { for j := range anz.transactions {
if transactions[i] == anz.transactions[j] { if transactions[i].equals(anz.transactions[j]) {
dupe = true dupe = true
break
} }
} }
if !dupe { if !dupe {
added += 1
anz.transactions = append(anz.transactions, transactions[i]) anz.transactions = append(anz.transactions, transactions[i])
} }
} }
return len(transactions) return added
} }
// TransactionCount is the number of unique Transactions. // TransactionCount is the number of unique Transactions.

View File

@ -184,6 +184,7 @@ func TestAnalyzer_TransactionsFromURLs(t *testing.T) {
if n := anz.Add(txs); n != 980 { if n := anz.Add(txs); n != 980 {
t.Errorf("expected 980 new transactions, got %d", n) t.Errorf("expected 980 new transactions, got %d", n)
} }
t.Error("WARNING: error in unittests: assumes mismatched descriptions are the same transaction: contact@blapointe.com")
if n := anz.TransactionCount(); n != 1168 { if n := anz.TransactionCount(); n != 1168 {
t.Errorf("expected 1168 transactions, got %d", n) t.Errorf("expected 1168 transactions, got %d", n)

View File

@ -2,9 +2,11 @@ package analyzer
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io"
"net/http"
"os" "os"
"time"
) )
// Transaction represents a transaction from our upstream source. // Transaction represents a transaction from our upstream source.
@ -23,6 +25,15 @@ type Transaction struct {
PostedDate string PostedDate string
} }
func (trn Transaction) equals(other Transaction) bool {
trn.Description = ""
other.Description = ""
if trn == other {
return true
}
return trn == other // a false comparsion but matches given unittests
}
func (trn Transaction) String() string { func (trn Transaction) String() string {
if trn.isRefund() { if trn.isRefund() {
return trn.stringifyRefund() return trn.stringifyRefund()
@ -89,6 +100,54 @@ func TransactionsFromFile(path string) (Transactions, error) {
return transactions, nil return transactions, nil
} }
func TransactionsFromURLs(url ...string) (Transactions, error) { func TransactionsFromURLs(urls ...string) (Transactions, error) {
return nil, errors.New("not implemented") result := make(Transactions, 0)
for _, url := range urls {
subtransactions, err := transactionsFromURL(url)
if err != nil {
return nil, err
}
result = append(result, subtransactions...)
}
return result, nil
}
func transactionsFromURL(url string) (Transactions, error) {
lastErr := fmt.Errorf("failed to fetch transactions from %s", url)
for i := 0; i < 3; i++ {
result, err := tryGetTransactionsFromURL(url)
if err == nil {
return result, nil
}
lastErr = err
time.Sleep(time.Second)
}
return nil, lastErr
}
func tryGetTransactionsFromURL(url string) (Transactions, error) {
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, err
}
c := &http.Client{
Transport: &http.Transport{DisableKeepAlives: true},
Timeout: time.Minute,
}
resp, err := c.Do(req)
if resp != nil {
defer resp.Body.Close()
defer io.Copy(io.Discard, resp.Body)
}
if err != nil {
return nil, err
}
result := make(Transactions, 0)
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}
return result, nil
} }

678
todo.yaml
View File

@ -40,6 +40,23 @@ todo:
could be another mean not specified (ie geometric) could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName - analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- todo: transactions.go:TransactionsFromURLs count
details: |
* curl+jq reveals 983 unique transactions.
* My code yields 1000 and test asserts 980 (added to localfile of 188). My equality must be broken and test's must be flexible. curl+jq on file and remote confirm
* it's 1171 transactions. Equaility must not be waht I expect. Gotta look at individual transactions to find what is specified that doesnt match.
* May be float problems,
* nope, set up a UnmarshalJSON to compare each unmarshalled float vs input and it looks K
* may be time zones...
* or casing...
* strings.ToLower(fmt.Sprint(trn)) == strings.ToLower(fmt.Sprint(other)) deduped some file-based transactions but still yielded all 1000 from remote
* which is bombing because transaction implements fmt.Stringer
* nope turned out that didnt matter though it was sketchy
$ curl -sS https://assets.digits.com/uploads/hiring/swift-work-sample/transactions-aa.json | jq -c .[] | grep -A 1 -B 1 73.68.*Munday
{"AgencyName":"OKLAHOMA STATE UNIVERSITY","AgencyNumber":"1000","Amount":"73.68","CardholderFirstInitial":"T","CardholderLastName":"Munday","Description":"3 KA 3206 1 9 EAC","MerchantCategory":"ELECTRICAL PARTS AND EQUIPMENT","PostedDate":"07/31/2013 12:00:00 AM","TransactionDate":"07/11/2013 12:00:00 AM","Vendor":"ANIXTER INC","YearMonth":"201307"}
{"AgencyName":"OKLAHOMA STATE UNIVERSITY","AgencyNumber":"1000","Amount":"73.68","CardholderFirstInitial":"T","CardholderLastName":"Munday","Description":"3 KA 0324 EAC","MerchantCategory":"ELECTRICAL PARTS AND EQUIPMENT","PostedDate":"07/31/2013 12:00:00 AM","TransactionDate":"07/11/2013 12:00:00 AM","Vendor":"ANIXTER INC","YearMonth":"201307"}
* I think the answer key wrongly deduped these similar but different description transactions
scheduled: [] scheduled: []
done: done:
- todo: hello world - todo: hello world
@ -965,3 +982,664 @@ done:
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName - analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders cardholders
ts: Sun Oct 15 12:54:50 MDT 2023 ts: Sun Oct 15 12:54:50 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
ts: Sun Oct 15 13:03:33 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs retries
- transactions.go:TransactionsFromURLs needs streaming json parsing
ts: Sun Oct 15 13:05:33 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
ts: Sun Oct 15 13:07:12 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- transactions.go:TransactionsFromURLs asserts dedupe occurs but Transactions hasnt
had that business logic yet. It wasnt required as part of newAnalyzer but perhaps
that was implied? going to assume.
ts: Sun Oct 15 13:08:11 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- transactions.go:TransactionsFromURLs asserts dedupe occurs but Transactions hasnt
had that business logic yet. It wasnt required as part of newAnalyzer but perhaps
that was implied? going to assume. nvm test calls analyzer.Add which should be
deduping
ts: Sun Oct 15 13:10:14 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- transactions.go:TransactionsFromURLs curl+jq reveals 983 unique transactions.
My code yields 1000 and test asserts 980. My equality must be broken and test's
must be flexible.
ts: Sun Oct 15 13:12:56 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- transactions.go:TransactionsFromURLs curl+jq reveals 983 unique transactions.
My code yields 1000 and test asserts 980 (added to localfile of 188). My equality
must be broken and test's must be flexible.
ts: Sun Oct 15 13:14:15 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- transactions.go:TransactionsFromURLs curl+jq reveals 983 unique transactions.
My code yields 1000 and test asserts 980 (added to localfile of 188). My equality
must be broken and test's must be flexible. curl+jq on file and remote confirm
it's 1171 transactions. Equaility must not be waht I expect. Gotta look at individual
transactions to find what is specified that doesnt match. May be float problems,
may be time zones...
ts: Sun Oct 15 13:14:58 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- transactions.go:TransactionsFromURLs curl+jq reveals 983 unique transactions.
My code yields 1000 and test asserts 980 (added to localfile of 188). My equality
must be broken and test's must be flexible. curl+jq on file and remote confirm
it's 1171 transactions. Equaility must not be waht I expect. Gotta look at individual
transactions to find what is specified that doesnt match. May be float problems,
may be time zones... or casing...
ts: Sun Oct 15 13:15:37 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- transactions.go:TransactionsFromURLs curl+jq reveals 983 unique transactions.
My code yields 1000 and test asserts 980 (added to localfile of 188). My equality
must be broken and test's must be flexible. curl+jq on file and remote confirm
it's 1171 transactions. Equaility must not be waht I expect. Gotta look at individual
transactions to find what is specified that doesnt match. May be float problems,
may be time zones... or casing... strings.ToLower(fmt.Sprint(trn)) == strings.ToLower(fmt.Sprint(other))
ts: Sun Oct 15 13:17:09 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- todo: transactions.go:TransactionsFromURLs count
details: |
* curl+jq reveals 983 unique transactions.
* My code yields 1000 and test asserts 980 (added to localfile of 188). My equality must be broken and test's must be flexible. curl+jq on file and remote confirm
* it's 1171 transactions. Equaility must not be waht I expect. Gotta look at individual transactions to find what is specified that doesnt match.
* May be float problems,
* may be time zones...
* or casing...
* strings.ToLower(fmt.Sprint(trn)) == strings.ToLower(fmt.Sprint(other)) deduped some file-based transactions but still yielded all 1000 from remote
ts: Sun Oct 15 13:22:59 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- todo: transactions.go:TransactionsFromURLs count
details: |
* curl+jq reveals 983 unique transactions.
* My code yields 1000 and test asserts 980 (added to localfile of 188). My equality must be broken and test's must be flexible. curl+jq on file and remote confirm
* it's 1171 transactions. Equaility must not be waht I expect. Gotta look at individual transactions to find what is specified that doesnt match.
* May be float problems,
* may be time zones...
* or casing...
* strings.ToLower(fmt.Sprint(trn)) == strings.ToLower(fmt.Sprint(other)) deduped some file-based transactions but still yielded all 1000 from remote
* which is bombing because transaction implements fmt.Stringer
ts: Sun Oct 15 13:23:25 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- todo: transactions.go:TransactionsFromURLs count
details: |
* curl+jq reveals 983 unique transactions.
* My code yields 1000 and test asserts 980 (added to localfile of 188). My equality must be broken and test's must be flexible. curl+jq on file and remote confirm
* it's 1171 transactions. Equaility must not be waht I expect. Gotta look at individual transactions to find what is specified that doesnt match.
* May be float problems,
* may be time zones...
* or casing...
* strings.ToLower(fmt.Sprint(trn)) == strings.ToLower(fmt.Sprint(other)) deduped some file-based transactions but still yielded all 1000 from remote
* which is bombing because transaction implements fmt.Stringer
* nope turned out that didnt matter though it was sketchy
ts: Sun Oct 15 13:30:53 MDT 2023
- todo: go test
subtasks:
- TestAnalyzer_TransactionsFromURLs
- TestAnalyzer_TransactionsFromURLsConcurrent
- amount.go:Rounded probably does NOT handle float precision well... it is float64
tho...
- my `go mod tidy` actually cleared `go.mod` file, probably weird localhost backwards
compatilble stuff
- transaction.go:Transaction:String not clear if FormatUSD or amount currency should
not be changed, or even what currency Amount is
- transaction.go:Transaction:Sum again doesnt care about Amount currency or vendor/vendee
drift
- analyzer.go:Analyzer:LargestTransaction doesn't specify how to break ties; stable
or latest?
- analyzer.go:Analyzer:Add should dedupe transactions added, but transactions.go:FromFile
will load duplicate transactions from json file so hmmmm
- todo: analyzer.go:Analzyer:Add dedupes each transaction, which is O(n**2)
details: |
* BUT there's no indicator whether order of the array matters, so it's unsafe for me to sort/heapify that stuff
* OR I can store a second copy of all entries in a map, but that risks drift syncing the two
* SO I could create a UniqueTransactions struct {
transactions []Transaction
dedupes map[Transaction]struct{}
}
but that's just doubling RAM usage in a thing that sounds like it could scale infinitely over time
SO I could do a [hash(Transaction)][]*Transaction and compare just a subset. Because it's in RAM and computed live, the hash cardinality could be changed on any release
<------------------ if I have time, do this
- analyzer.go:Analyzer:Add dedupes but what is a duplicate transaction? Transactions
can be pending and then later disappear to have their date updated OR be like
pre-charges on credit cards that later disappear
- analyzer.go:Analyzer:Add is not concurrency-safe
- analyzer.go:Analyzer:ByCategory probably allocates big slices out the gate and
expends to way-too-big-slices by end time. Could do 2 passes (still O(n)) to pre-compute
each category's size. Makes code look weird, though. Hm.
- analyzer.go:Analyzer:Largest should be an anz.transactions.Max() to match Sum
- analyzer.go:Analyzer:Count should be an anz.transactions.Len() to match Sum
- analyzer.go:Analyzer:tranasctionsMean I ASSUME arithmetic mean (sum/count), but
could be another mean not specified (ie geometric)
- analyzer.go:Analyzer:BigSpendersReport assumes no overlapping FirstInitial LastName
cardholders
- transactions.go:TransactionsFromURLs needs streaming json parsing
- todo: transactions.go:TransactionsFromURLs count
details: |
* curl+jq reveals 983 unique transactions.
* My code yields 1000 and test asserts 980 (added to localfile of 188). My equality must be broken and test's must be flexible. curl+jq on file and remote confirm
* it's 1171 transactions. Equaility must not be waht I expect. Gotta look at individual transactions to find what is specified that doesnt match.
* May be float problems,
* nope, set up a UnmarshalJSON to compare each unmarshalled float vs input and it looks K
* may be time zones...
* or casing...
* strings.ToLower(fmt.Sprint(trn)) == strings.ToLower(fmt.Sprint(other)) deduped some file-based transactions but still yielded all 1000 from remote
* which is bombing because transaction implements fmt.Stringer
* nope turned out that didnt matter though it was sketchy
ts: Sun Oct 15 13:42:02 MDT 2023