From 00c72df281fcd88361be7e16970d9a3d07de6707 Mon Sep 17 00:00:00 2001 From: Dominik Roth Date: Wed, 16 Jun 2021 15:12:26 +0200 Subject: [PATCH] Added a CLI-Interface and 'analyze' command --- main.py | 157 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 128 insertions(+), 29 deletions(-) diff --git a/main.py b/main.py index 62db33a..7deaec3 100644 --- a/main.py +++ b/main.py @@ -306,7 +306,7 @@ def scoreUnread(G, globMu, globStd, errorFac=0.6): node['score'] = None -def printBestList(G, num=25): +def printBestList(G, num=-1): bestlist = [] for n in list(G.nodes): node = G.nodes[n] @@ -317,7 +317,7 @@ def printBestList(G, num=25): for i, book in enumerate(bestlist): print("["+str(i+1).zfill(int(math.log10(num)+1))+"] "+book['title'] + " ("+" & ".join(book['authors'])+"): {:.5f}".format(book['score'])) - if i == num-1: + if num!=-1 and i == num-1: break @@ -475,12 +475,8 @@ def genScores(G, books): return globMu, globStd -def recommendNBooks(n): - G, books = buildFullGraph() - mu, std = genScores(G, books) - +def recommendNBooks(G, mu, std, n): removeRestOfSeries(G) - removePriv(G) removeBad(G, mu-std-1.5) removeKeepBest(G, int(n*2) + 5, maxDistForRead=1.5) removeEdge(G) @@ -501,15 +497,7 @@ def recommendNBooks(n): scaleOpinionsByRating(G) addScoreToLabels(G) - printBestList(G, num=n) - genAndShowHTML(G, True) - - -def fullGraph(): - G, books = buildFullGraph() - mu, std = genScores(G, books) - - removePriv(G) +def fullGraph(G): removeEdge(G) removeHighSpanTags(G, 7) removeDangling(G, alsoBooks=False) @@ -521,19 +509,14 @@ def fullGraph(): scaleOpinionsByRating(G) addScoreToLabels(G) - printBestList(G, num=100) - genAndShowHTML(G) - -def readBooksAnalysis(): - G, books = buildFullGraph() - mu, std = genScores(G, books) - - removePriv(G) +def readBooksAnalysis(G, minRating=0, showAllTags=True, removeUnconnected=False): removeUnread(G) - removeEdge(G) + removeBad(G, minRating) + if not showAllTags: + removeEdge(G) removeHighSpanTags(G, 15) - removeDangling(G, alsoBooks=False) + removeDangling(G, alsoBooks=removeUnconnected) removeTopLists(G) pruneTags(G, 8) @@ -541,9 +524,125 @@ def readBooksAnalysis(): scaleOpinionsByRating(G) addScoreToLabels(G) - printBestList(G, num=100) - genAndShowHTML(G) +def analyze(G, type_name, name, dist=2.7): + from fuzzywuzzy import fuzz + type_ident = type_name[0] + full_name = type_ident + "/" + name + bestRatio, match, n = 0, None, 0 + for ni in list(G.nodes): + node = G.nodes[ni] + if node['t'] == type_name or type_name=="any": + if name==node['label'] or full_name==node['label']: + match, n = node, ni + break + ratio = fuzz.ratio(node['label'], name) + if ratio > bestRatio: + bestRatio, match, n = ratio, node, ni + menge = set() + pruneDist(G, match, n, dist, menge) + for n in list(G.nodes): + if n not in menge: + G.remove_node(n) + removeHighSpanTags(G, 12) + if dist > 1: + removeDangling(G, True) + + scaleBooksByRating(G) + scaleOpinionsByRating(G) + match['value'] += 100 + addScoreToLabels(G) + +def pruneDist(G, node, n, dist, menge, firstEdge=False): + if dist <= 0: + return + dist -= 1 + if menge==set(): + firstEdge=True + menge.add(n) + if node['t'] in ['tag']: + if firstEdge: + dist-=0.1 + else: + return + bestlist = [] + keeplist = [] + for m in list(G.adj[n]): + book = G.nodes[m] + if book['t'] not in ['topList']: + if 'score' in book and book['score'] != None: + bestlist.append(book) + elif 'rating' in book and book['rating'] != None: + keeplist.append(book) + else: + book['score'] = 0 + bestlist.append(book) + bestlist.sort(key=lambda node: node['score'], reverse=True) + toKeep = min(int(dist*10), math.ceil(len(bestlist) * dist - len(keeplist)*0.5)) + if toKeep <= 0: + keeplist.sort(key=lambda node: node['rating'], reverse=True) + keeplist = keeplist[:min(int(dist*10), int(len(keeplist) * dist))] + bestlist = [] + else: + bestlist = bestlist[:toKeep] + + for m in list(G.adj[n]): + node = G.nodes[m] + if node in bestlist or node in keeplist: + pruneDist(G, node, m, dist, menge, firstEdge=firstEdge) + +def cliInterface(): + import argparse + + parser = argparse.ArgumentParser(description='TODO: Write Description.') + parser.add_argument('--keep-priv', action="store_true") + parser.add_argument('--remove-read', action="store_true") + parser.add_argument('--remove-unread', action="store_true") + parser.add_argument('--no-web', action="store_true") + parser.add_argument('--no-list', action="store_true") + cmds = parser.add_subparsers(required=True, dest='cmd') + + p_rec = cmds.add_parser('recommend', description="TODO", aliases=['rec']) + p_rec.add_argument('-n', type=int, default=25, help='number of books to recommend') + + p_read = cmds.add_parser('read', description="TODO", aliases=[]) + p_read.add_argument('--min-rating', type=int, default=0) + p_read.add_argument('--all-tags', action="store_true") + p_read.add_argument('--only-connected', action="store_true") + + p_show = cmds.add_parser('analyze', description="TODO", aliases=[]) + p_show.add_argument('type', choices=['any', 'book', 'recommender', 'author', 'series']) + p_show.add_argument('name', type=str) + p_show.add_argument('-d', type=float, default=2.7, help='depth of expansion') + + p_full = cmds.add_parser('full', description="TODO", aliases=[]) + + args = parser.parse_args() + + G, books = buildFullGraph() + mu, std = genScores(G, books) + if not args.keep_priv: + removePriv(G) + if args.remove_read: + removeRead(G) + elif args.remove_unread: + removeUnread(G) + + if args.cmd=="recommend": + recommendNBooks(G, mu, std, args.n) + elif args.cmd=="read": + readBooksAnalysis(G, args.min_rating, args.all_tags, args.only_connected) + elif args.cmd=="analyze": + analyze(G, args.type, args.name, args.d) + elif args.cmd=="full": + fullGraph(G) + else: + raise Exception("Bad") + + if not args.no_list: + printBestList(G) + if not args.no_web: + genAndShowHTML(G) if __name__ == "__main__": - recommendNBooks(45) + cliInterface()