KageNoOni

Decklist.py

Jan 25th, 2013
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.42 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. import os
  4.  
  5. HOME = os.path.expanduser(os.path.join("~", "Documents", "Decks"))
  6. if HOME[-1] != '/':
  7.     HOME += '/'
  8.  
  9. try:
  10.     from Tkinter import Tk
  11. except ImportError:
  12.     from tkinter import Tk
  13.     cmd_input = input
  14. else:
  15.     cmd_input = raw_input
  16. from fnmatch import fnmatch
  17.  
  18. cpd = Tk()
  19. cpd.withdraw()
  20.  
  21. class Decklist:
  22.     def __init__(self):
  23.         self.cards = list()
  24.         self.cat = str()
  25.         self.cats = dict()
  26.         self.catList = list()
  27.         self.prompt = '> '
  28.         self.title = 'No Title'
  29.  
  30.     def add(self, numberOfCards, cardName, cat):
  31.         cards = self.cats[cat]
  32.         cards.append((int(numberOfCards), cardName))
  33.         self.cats[cat] = cards
  34.  
  35.     def remove(self, index, cat):
  36.         cards = self.cats[cat]
  37.         if index.isdigit():
  38.             del cards[int(index)]
  39.             self.cats[cat] = cards
  40.             return
  41.         else:
  42.             raise ValueError('An index must be passed')
  43.  
  44.     def addcat(self, cat):
  45.         if cat in self.catList:
  46.             raise ValueError('%s already exists.' % cat)
  47.         self.cats[cat] = list()
  48.         self.catList.append(cat)
  49.  
  50.     def removecat(self, cat):
  51.         if not cat in self.cats.keys():
  52.             raise KeyError('%s doesn\'t exist.' % cat)
  53.         del self.cats[cat]
  54.         self.catList.remove(cat)
  55.  
  56.     def clear(self):
  57.         self.cards = []
  58.         self.cat = ''
  59.         self.cats = {}
  60.         self.catList = []
  61.         self.prompt = '> '
  62.         self.title = 'No Title'
  63.  
  64.     def save(self, name):
  65.         filepath = makeDirAndName(name)
  66.         deckfile = open(filepath, 'w')
  67.  
  68.         data = '[Meta]\n'
  69.         data += 'Title=%s\n' % self.title
  70.  
  71.         for cat in self.catList:
  72.             data += '[%s]\n' % cat
  73.             cards = self.cats[cat]
  74.             if len(cards) == 0:
  75.                 continue
  76.             for index in range(len(cards)):
  77.                 cardData = cards[index]
  78.                 data += 'n%s=%s\n' % (index, cardData[0])
  79.                 data += 'card%s=%s\n' % (index, cardData[1])
  80.         deckfile.write(data)
  81.  
  82.     def load(self, name):
  83.         filepath = makeDirAndName(name)
  84.         deckfile = open(filepath, 'r')
  85.  
  86.         catList, data = iniparse(deckfile.read())
  87.         deckfile.close()
  88.  
  89.         self.clear()
  90.         if 'Title' in data['Meta'].keys():
  91.             self.title = data['Meta']['Title']
  92.         if 'Comment' in data['Meta'].keys():
  93.             self.comment = data['Meta']['Comment']
  94.  
  95.         catList.remove('Meta')
  96.         for cat in catList:
  97.             self.addcat(cat)
  98.             cardData = data[cat]
  99.  
  100.             index = 0
  101.             while True:
  102.                 try:
  103.                     numberOfCards = cardData['n%s' % index]
  104.                     cardName = cardData['card%s' % index]
  105.                 except KeyError:
  106.                     break
  107.                 self.add(numberOfCards, cardName, cat)
  108.                 index += 1
  109.  
  110.     def getDeckList(self, options):
  111.         deck = self.title + '\n'
  112.         for cat in self.catList:
  113.             if len(self.cats[cat]) == 0:
  114.                 continue
  115.             deck += '  %s\n' % cat
  116.             for card in self.cats[cat]:
  117.                 if options['autocard'] == True:
  118.                     deck += '   %sx [c]%s[/c]\n' % (card[0], card[1])
  119.                 elif options['link'] == True:
  120.                     deck += '   %sx <a target="Magic" href="http://gatherer.wizards.com/pages/card/details.aspx?name=%s">%s</a>\n' % (card[0], card[1].replace(' ', '%20'), card[1])
  121.                 else:
  122.                     deck += '   %sx %s\n' % (card[0], card[1])
  123.         return deck[:-1]
  124.  
  125.     def getHtmlDeck(self, options):
  126.         tempCatList = self.catList
  127.         catList = list()
  128.         cardnum = 0
  129.         for cat in tempCatList:
  130.             if len(self.cats[cat]) > 0:
  131.                 catList.append(cat)
  132.  
  133.         table = '<table border="1" cellspacing="0">\n<tbody>\n<tr>\n'
  134.         table += '<th colspan="%s" style="text-align: center;"><big>%s' % (len(catList), self.title)
  135.         table += '</big></th>\n'
  136.         table += '</tr>\n'
  137.  
  138.         table += '<tr>\n'
  139.         for cat in catList:
  140.             table += '<th>%s</th>\n' % cat
  141.         table += '</tr>\n'
  142.  
  143.         table += '<tr>\n'
  144.         for cat in catList:
  145.             table += '<td valign="top">\n'
  146.             cardList = self.cats[cat]
  147.             for index in range(len(cardList)):
  148.                 cardData = cardList[index]
  149.                 if options['autocard'] == True:
  150.                     table += '%sx [c]%s[/c]<br />\n' % (cardData[0], cardData[1])
  151.                 elif options['link'] == True:
  152.                     table += '%sx &lt;a target="Magic" href="http://gatherer.wizards.com/pages/card/details.aspx?name=%s"&gt;%s&lt;/a&gt;<br />\n' % (cardData[0], cardData[1].replace(' ', '%20'), cardData[1])
  153.                 else:
  154.                     table += '%sx %s<br />\n' % (cardData[0], cardData[1])
  155.                 cardnum += int(cardData[0])
  156.             table += '</td>\n'
  157.         table += '</tr>\n<tr>\n'
  158.         for cat in catList:
  159.             total = 0
  160.             for cardData in self.cats[cat]:
  161.                 total += int(cardData[0])
  162.             table += '<td>%s cards</td>\n' % (total)
  163.         table += '</tr>\n<tr>\n'
  164.         table += '<th colspan="%s">' % len(catList)
  165.         table += '%s Total' % cardnum
  166.         table += '</th>\n</tr>\n</tbody>\n</table>'
  167.         return table
  168.  
  169.     def getListOfDecks(self):
  170.         dirs = list()
  171.         decks = list()
  172.         startdir = HOME
  173.         dirs.append(startdir)
  174.  
  175.         while True:
  176.             cwd = dirs.pop()
  177.             shortdir = cwd[len(startdir)+1:]
  178.             cwddirs = sorted(os.listdir(cwd))
  179.  
  180.             for direc in cwddirs:
  181.                 path = startdir + '/' + direc
  182.                 if os.path.isdir(path):
  183.                     dirs.append(path)
  184.                     continue
  185.  
  186.                 if fnmatch(direc, '*.dck'):
  187.                     if len(shortdir) != 0:
  188.                         deck = shortdir+'/'+direc[:-4]
  189.                         decks.append(deck)
  190.                     else:
  191.                         decks.append(direc[:-4])
  192.                     continue
  193.  
  194.             if len(dirs) == 0:
  195.                 break
  196.        
  197.         return decks
  198.  
  199.     def cmd_clear(self, args):
  200.         """Start a new blank decklist, clears away previous existing data.
  201.         No syntax needed."""
  202.         self.clear()
  203.         print('Decklist has been cleared.')
  204.  
  205.     def cmd_name(self, args):
  206.         """Syntax: name <deck name>
  207.         Change the deck name to <deck name>"""
  208.         if args == '':
  209.             print('No deck name given.')
  210.             print('name <deck name>')
  211.             return
  212.  
  213.         self.title = args
  214.         print('Deck name changed to "%s"' % args)
  215.  
  216.     def cmd_add(self, args):
  217.         """Syntax: add <number> <card name>
  218.         Adds <number> of <card name> to the current category.
  219.         You need to select a category before you can use this command.
  220.         cat <category>"""
  221.         if self.cat == '':
  222.             print('No category was specified.\nChoose a category then add cards to it.\ncat <category>')
  223.             return
  224.        
  225.         if args == '':
  226.             print('No card data was entered.\nadd <number> <card name>')
  227.             return
  228.  
  229.         try:
  230.             num, cardname = args.split(' ', 1)
  231.         except ValueError:
  232.             print('You need to specify the number of the card to add, then the cardname.\nadd <number> <card name>')
  233.        
  234.         try:
  235.             num = int(num)
  236.         except ValueError:
  237.             print('Unable to understand your request. Please format the request correctly. <number> needs to be a number.\nadd <number> <card name>')
  238.             return
  239.        
  240.         self.cats[self.cat].append((num, cardname))
  241.  
  242.     def cmd_del(self, args):
  243.         """Syntax: del <index>
  244.         Deletes a card from the currently selected category.
  245.         <index> must be the index from the card list you want deleted."""
  246.         if self.cat == '':
  247.             print('No category set yet.\ncat <category>')
  248.             return
  249.        
  250.         if args == '':
  251.             print('No card was specified.\ndel <card>\n<card> can be the card index or the card name.')
  252.             return
  253.  
  254.         try:
  255.             self.remove(args, self.cat)
  256.         except IndexError:
  257.             print('The card index is higher than any existing index.')
  258.         except ValueError:
  259.             print('You need to give a number as the index.')
  260.             print('del <index>')
  261.  
  262.     def cmd_replace(self, args):
  263.         """Syntax: replace <index> <number> <card name>
  264.         Replace the chosen card with another card.
  265.         Example: replace 0 12 Swamp
  266.         That replaces the first card entry with a new one with 12 Swamp cards."""
  267.         if self.cat == '':
  268.             print('No category selected yet.')
  269.             print('cat <category>')
  270.  
  271.         if args == '':
  272.             print('No information given with this command.')
  273.             print('You need to specify the index to be replaced,')
  274.             print('the quantity of the replacement card, and the')
  275.             print('replacement card\'s name.')
  276.             print('replace <index> <number> <card name>')
  277.             return
  278.         try:
  279.             index, num, name = args.split(' ', 2)
  280.         except ValueError:
  281.             print('Not enough information given. You need to include')
  282.             print('the index to be replaced, and the quantity and name')
  283.             print('of the replacement card.')
  284.             print('replace <index> <number> <card name>')
  285.             return
  286.  
  287.         try:
  288.             index, num = (int(index), int(num))
  289.         except ValueError:
  290.             print('Both <index> and <number> need to be numbers.')
  291.             print('replace <index> <number> <card name>')
  292.             return
  293.  
  294.         cards = self.cats[self.cat]
  295.         cards[index] = (num, name)
  296.         self.cats[self.cat] = cards
  297.  
  298.     def cmd_cat(self, args):
  299.         """Syntax: cat <category>
  300.         Selects the chosen category, creates it if it doesn't already exist.
  301.         """
  302.         if args == '':
  303.             print('No category given. You must specify a category to select it.\ncat <category>')
  304.        
  305.         if args not in self.catList:
  306.             self.addcat(args)
  307.  
  308.         self.cat = args
  309.         self.prompt = args + '> '
  310.         self.cards = self.cats[args]
  311.  
  312.     def cmd_cats(self, args):
  313.         """Syntax: cats
  314.         Prints a list of all current categories"""
  315.         if len(self.catList) == 0:
  316.             print('No categories defined.\ncat <category>')
  317.             return
  318.  
  319.         msg = ''
  320.         for index in range(len(self.catList)):
  321.             if len(self.catList) > 1 and index == len(self.catList):
  322.                 msg += ', and %s.' % self.catList[index]
  323.             elif len(self.catList) == 1 and index == 1:
  324.                 msg += ' and %s.' % self.catList[index]
  325.             elif index == 0:
  326.                 msg = self.catList[index]
  327.             else:
  328.                 msg += ', %s' % self.catList[index]
  329.         print('Categories:\n' + msg)
  330.  
  331.     def cmd_delcat(self, args):
  332.         """Syntax: delcat <category>
  333.         Deletes the chosen category."""
  334.         if args == '':
  335.             print('You need to specify a category.\ndelcat <category>')
  336.             return
  337.        
  338.         try:
  339.             self.removecat(args)
  340.         except KeyError:
  341.             print("Category %s doesn't exist." % args)
  342.         else:
  343.             print("Category %s has been deleted." % args)
  344.  
  345.     def cmd_save(self, args):
  346.         """Syntax: save <name>
  347.         Saves the deck as the chosen name."""
  348.         if args == '':
  349.             print('No deck specified.')
  350.             return
  351.        
  352.         try:
  353.             self.save(args)
  354.         except IOError:
  355.             print('Invalid path: %s' % (HOME + args + '.dck'))
  356.         else:
  357.             print('Saved %s.' % args)
  358.  
  359.     def cmd_load(self, args):
  360.         """Syntax: load <name>
  361.         Loads the deck with the chosen name."""
  362.         if args == '':
  363.             print('No deck specified.')
  364.             return
  365.        
  366.         try:
  367.             self.load(args)
  368.         except IOError:
  369.             print('Invalid path: %s' % HOME + args + '.dck')
  370.         else:
  371.             print('Loaded %s.' % args)
  372.  
  373.     def cmd_listdecks(self, args):
  374.         """No syntax needed. Just type 'decks'.
  375.         This will list the decks you've saved, sorted by directory.
  376.         """
  377.  
  378.         decks = self.getListOfDecks()
  379.  
  380.         if len(decks) == 0:
  381.             print('No decks saved yet.')
  382.             return
  383.  
  384.         print('Saved Decks:')
  385.         for deck in decks:
  386.             print(deck)
  387.  
  388.     def cmd_print(self, args):
  389.         """Syntax: print [-flags]
  390.         Prints a decklist, you can change the appearance by specifying flags.
  391.         Print a decklist using an HTML table: print -h
  392.         Print a decklist that autocards: print -c
  393.         Print a decklist with direct links to Gatherer cards: print -l
  394.         Flags can be mixed, though -c and -l don't mix.
  395.         Print a decklist that autocards in an HTML table: print -hc
  396.         """
  397.        
  398.         args = args.split()
  399.         options = {'autocard': False, 'html': False, 'link': False}
  400.         for arg in args:
  401.             if arg[0] != '-':
  402.                 continue
  403.             for char in arg:
  404.                 if char == '-':
  405.                     continue
  406.                 if char == 'c' and options['link'] == False:
  407.                     options['autocard'] = True
  408.                     continue
  409.                 if char == 'h':
  410.                     options['html'] = True
  411.                 if char == 'l' and options['autocard'] == False:
  412.                     options['link'] = True
  413.         if options['html'] == True:
  414.             deck = self.getHtmlDeck(options)
  415.         else:
  416.             deck = self.getDeckList(options)
  417.         print(deck+'\n')
  418.         cpd.clipboard_clear()
  419.         cpd.clipboard_append(deck)
  420.         cmd_input('Press any key to continue.')
  421.  
  422. def iniparse(data):
  423.     struct = dict()
  424.     cat = None
  425.     catList = list()
  426.     for line in data.split('\n'):
  427.         if len(line) > 2 and line[0] == '[' and line[-1] == ']':
  428.             cat = line[1:-1]
  429.             struct[cat] = dict()
  430.             catList.append(cat)
  431.             continue
  432.         else:
  433.             if type(line) != str or len(line) == 0:
  434.                 break
  435.             key, value = line.split('=', 1)
  436.             struct[cat][key] = value
  437.     return (catList, struct)
  438.  
  439. def makeDirAndName(name):
  440.     filepath = HOME + name + '.dck'
  441.     path = filepath.split('/')
  442.     name = path.pop()
  443.     path = '/'.join(path) + '/'
  444.     if not os.path.exists(path):
  445.         os.makedirs(path)
  446.     return path + name
  447.  
  448. def main():
  449.     dl = Decklist()
  450.     cmds = {
  451.         'add': dl.cmd_add,
  452.         'cat': dl.cmd_cat,
  453.         'cats': dl.cmd_cats,
  454.         'clear': dl.cmd_clear,
  455.         'decks': dl.cmd_listdecks,
  456.         'del': dl.cmd_del,
  457.         'delcat': dl.cmd_delcat,
  458.         'load': dl.cmd_load,
  459.         'name': dl.cmd_name,
  460.         'print': dl.cmd_print,
  461.         'replace': dl.cmd_replace,
  462.         'save': dl.cmd_save
  463.     }
  464.     keys = list()
  465.     for key in cmds:
  466.         keys.append(key)
  467.     keys.sort()
  468.     while True:
  469.         if dl.cat == '':
  470.             dl.prompt = '> '
  471.         elif dl.cat not in dl.cats.keys():
  472.             dl.cat = ''
  473.             dl.prompt = '> '
  474.         else:
  475.             dl.cards = dl.cats[dl.cat]
  476.             print(dl.cat)
  477.             for index in range(len(dl.cards)):
  478.                 card = dl.cards[index]
  479.                 print('%2d) %2dx %s' % (index, card[0], card[1]) )
  480.  
  481.         cmd = cmd_input('\n'+dl.prompt).rstrip().split(None, 1)
  482.         print('')
  483.  
  484.         if cmd == '':
  485.             continue
  486.  
  487.         if len(cmd) == 2:
  488.             args = cmd.pop()
  489.         else:
  490.             args = ''
  491.         cmd = cmd[0].lower()
  492.  
  493.         if cmd == 'exit':
  494.             break
  495.  
  496.         if cmd == 'help':
  497.             if args == '':
  498.                 print('The commands are:')
  499.                 keys.sort()
  500.                 for key in keys:
  501.                     print(key)
  502.                 print("\nType 'help' followed by the name of the command you want to learn more about the command.\n")
  503.             elif (args.split()[0].lower() in cmds.keys()):
  504.                 key = args.split()[0].lower()
  505.                 print(cmds[key].__doc__)
  506.             else:
  507.                 print("You didn't give a valid command to find help on.")
  508.             continue
  509.  
  510.         if cmd not in keys:
  511.             print("%s is not a valid command." % cmd)
  512.             continue
  513.  
  514.         cmds[cmd](args)
  515.  
  516. if __name__ == "__main__":
  517.     main()
Advertisement
Add Comment
Please, Sign In to add comment