# Path: lib/fpos/core.py
# def money(value):
# def lcs(a, b):
# 
# Path: lib/fpos/core.py
# def money(value):
#     return "{:.2f}".format(value)
# 
# Path: lib/fpos/groups.py
# class DynamicGroups(GroupProtocol):
#     def __init__(self, threshold=0.85, size=4, backend=None):
#         if backend is None:
#             backend = SqlGroupCollection()
#         self.backend = backend
#         self._strgrp = Strgrp(threshold=threshold, size=size)
#         self.size = size
#         self.threshold = threshold
#         self.map = dict()
# 
#     def __iter__(self):
#         return iter(self._strgrp)
# 
#     def __enter__(self):
#         self.backend.__enter__()
#         return self
# 
#     def __exit__(self, exc_type, exc_value, traceback):
#         self.backend.__exit__(exc_type, exc_value, traceback)
# 
#     def _split_heap(self, heap):
#         i = None
# 
#         for i, grpbin in enumerate(heap):
#             acceptable = grpbin.is_acceptible(self._strgrp)
#             if not acceptable:
#                 r = (heap[:i], heap[i:])
#                 break
#         else:
#             r = (heap, [])
# 
#         return r
# 
#     def find_group(self, description):
#         grpbin = self._strgrp.grp_exact(description)
#         if grpbin is not None:
#             return grpbin
# 
#         did = gen_id(description, salt)
#         if self.backend.have_association(did):
#             cid = self.backend.get_canonical(did)
#             if cid in self.map:
#                 return self._strgrp.grp_exact(self.map[cid])
#             return None
# 
#         heap = self._strgrp.grps_for(description)
# 
#         if self.size == 0:
#             return heap[0] if len(heap) else None
# 
#         needles, haystack = self._split_heap(heap)
#         if len(needles) == 0:
#             return None
# 
#         dynamic = [n.is_dynamic(self._strgrp) for n in needles]
#         if sum(dynamic) == 1:
#             return needles[dynamic.index(True)]
# 
#         # Otherwise get user input
#         return self._request_match(description, needles)
# 
#     def insert(self, description, value, group=None):
#         did = gen_id(description, salt)
#         if group:
#             group.add(self._strgrp, description, value)
#             gid = gen_id(group.key(), salt)
#             cid = self.backend.get_canonical(gid);
#             if not self.backend.have_association(did):
#                 self.backend.associate(cid, did)
#         else:
#             group = self._strgrp.add(description, value)
#             if self.backend.have_association(did):
#                 cid = self.backend.get_canonical(did)
#                 self.map[cid] = description
#             else:
#                 self.map[did] = description
#                 self.backend.associate(did, did)
# 
#         return group
# 
#     def add(self, description, value):
#         return self.insert(description, value, self.find_group(description))


import argparse
import csv
import collections
import math
import re
from .core import categories
from .core import money
from .groups import DynamicGroups
                        # Category isn't known, output remains empty to
                        # trigger user input
                        pass
                if category is None:
                    # Haven't yet determined the category, require user input
                    group = tagger.find_group(cooked.description)
                    category = tagger.categorize(cooked, group, confirm)
                    assert None is not category
                    tagger.insert(cooked, category, group)
                    print()
                output = []
                # Retain the raw description string in the output
                output.extend(row[:3])
                output.append(category)
                annotated.append(output)
        except EOFError:
            pass
    return annotated

def main(args=None):
    if args is None:
        args = parse_args()
    try:
        r = csv.reader(args.infile, dialect='excel')
        w = csv.writer(args.outfile, dialect='excel')
        w.writerows(annotate(r, args.confirm))
    finally:
        args.infile.close()
        args.outfile.close()


# Path: lib/fpos/core.py
# def money(value):
# def lcs(a, b):
# 
# Path: lib/fpos/core.py
# def money(value):
#     return "{:.2f}".format(value)
# 
# Path: lib/fpos/groups.py
# class DynamicGroups(GroupProtocol):
#     def __init__(self, threshold=0.85, size=4, backend=None):
#         if backend is None:
#             backend = SqlGroupCollection()
#         self.backend = backend
#         self._strgrp = Strgrp(threshold=threshold, size=size)
#         self.size = size
#         self.threshold = threshold
#         self.map = dict()
# 
#     def __iter__(self):
#         return iter(self._strgrp)
# 
#     def __enter__(self):
#         self.backend.__enter__()
#         return self
# 
#     def __exit__(self, exc_type, exc_value, traceback):
#         self.backend.__exit__(exc_type, exc_value, traceback)
# 
#     def _split_heap(self, heap):
#         i = None
# 
#         for i, grpbin in enumerate(heap):
#             acceptable = grpbin.is_acceptible(self._strgrp)
#             if not acceptable:
#                 r = (heap[:i], heap[i:])
#                 break
#         else:
#             r = (heap, [])
# 
#         return r
# 
#     def find_group(self, description):
#         grpbin = self._strgrp.grp_exact(description)
#         if grpbin is not None:
#             return grpbin
# 
#         did = gen_id(description, salt)
#         if self.backend.have_association(did):
#             cid = self.backend.get_canonical(did)
#             if cid in self.map:
#                 return self._strgrp.grp_exact(self.map[cid])
#             return None
# 
#         heap = self._strgrp.grps_for(description)
# 
#         if self.size == 0:
#             return heap[0] if len(heap) else None
# 
#         needles, haystack = self._split_heap(heap)
#         if len(needles) == 0:
#             return None
# 
#         dynamic = [n.is_dynamic(self._strgrp) for n in needles]
#         if sum(dynamic) == 1:
#             return needles[dynamic.index(True)]
# 
#         # Otherwise get user input
#         return self._request_match(description, needles)
# 
#     def insert(self, description, value, group=None):
#         did = gen_id(description, salt)
#         if group:
#             group.add(self._strgrp, description, value)
#             gid = gen_id(group.key(), salt)
#             cid = self.backend.get_canonical(gid);
#             if not self.backend.have_association(did):
#                 self.backend.associate(cid, did)
#         else:
#             group = self._strgrp.add(description, value)
#             if self.backend.have_association(did):
#                 cid = self.backend.get_canonical(did)
#                 self.map[cid] = description
#             else:
#                 self.map[did] = description
#                 self.backend.associate(did, did)
# 
#         return group
# 
#     def add(self, description, value):
#         return self.insert(description, value, self.find_group(description))


# Path: lib/fpos/annotate.py
import argparse
import csv
import collections
import math
import re
from .core import categories
from .core import money
from .groups import DynamicGroups

                        # Category isn't known, output remains empty to
                        # trigger user input
                        pass
                if category is None:
                    # Haven't yet determined the category, require user input
                    group = tagger.find_group(cooked.description)
                    category = tagger.categorize(cooked, group, confirm)
                    assert None is not category
                    tagger.insert(cooked, category, group)
                    print()
                output = []
                # Retain the raw description string in the output
                output.extend(row[:3])
                output.append(category)
                annotated.append(output)
        except EOFError:
            pass
    return annotated

def main(args=None):
    if args is None:
        args = parse_args()
    try:
        r = csv.reader(args.infile, dialect='excel')
        w = csv.writer(args.outfile, dialect='excel')
        w.writerows(annotate(r, args.confirm))
    finally:
        args.infile.close()
        args.outfile.close()


if __name__ == "__main__":