diff --git a/dlibrary/dlibrary.py b/dlibrary/dlibrary.py index 3498072..03f7f4e 100755 --- a/dlibrary/dlibrary.py +++ b/dlibrary/dlibrary.py @@ -821,6 +821,47 @@ def copy_recursive(src, dest): else: shutil.copyfile(item, dest / item.name) + +memoized_similarities = {} + +def similarity(a, b): + if len(a) < len(b): + shorter = a + longer = b + else: + shorter = b + longer = a + if len(shorter) == 0: + return 0 + + if (shorter, longer) in memoized_similarities: + return memoized_similarities[(shorter, longer)] + + skip_similarity = similarity(shorter[1:], longer) + match_idx = longer.find(shorter[0]) + if match_idx == -1: + result = skip_similarity + else: + take_similarity = 1 + similarity(shorter[1:], longer[match_idx+1:]) + result = max(skip_similarity, take_similarity) + + memoized_similarities[(shorter, longer)] = result + return result + +def top(items, n, key): + if len(items) == 0: + return [] + winners = items[:1] + for item in items[1:]: + if len(winners) < n or key(item) > key(winners[-1]): + for i in range(len(winners)): + if key(item) > key(winners[i]): + winners.insert(i, item) + break + if len(winners) > n: + winners.pop() + return winners + def generate(args): jenv = Environment( loader=PackageLoader("dlibrary"), @@ -869,15 +910,25 @@ def generate(args): } works.append(work) - for work in works: + for (idx, work) in enumerate(works): + def suggestion_priority(other_work): + if other_work is work: + return -2 + if work['series'] and work['series'] == other_work['series']: + return -1 + return similarity(work['title'], other_work['title']) + suggested = top(works, 6, suggestion_priority) + work_dir = site_dir / 'works' / work['id'] viewer_dir = work_dir / 'view' viewer_dir.mkdir(parents=True, exist_ok=True) with open(work_dir / 'index.html', 'w') as f: - f.write(work_template.render(depth=2, work=work, title=work['title'], suggested=works[:5])) + f.write(work_template.render(depth=2, work=work, title=work['title'], suggested=suggested)) with open(viewer_dir / 'index.html', 'w') as f: f.write(viewer_template.render(depth=3, work=work, title=work['title'])) + print(f'\x1b[2K\r{idx+1}/{len(works)} works processed...', end='') + def make_categorization(categorization, query, work_filter, work_style_cards=False): categorization_dir = site_dir / categorization