Lucas de Souza 6 éve
szülő
commit
12a6453901
7 módosított fájl, 423 hozzáadás és 0 törlés
  1. 4 0
      csvconfig.txt
  2. 49 0
      filters/filter.py
  3. 21 0
      filters/ieeeFilter.py
  4. 21 0
      filters/scopusFilter.py
  5. 21 0
      filters/webScienceFilter.py
  6. 124 0
      helpers.py
  7. 183 0
      main.py

+ 4 - 0
csvconfig.txt

@@ -0,0 +1,4 @@
+csvs/export2019.04.04-15.12.40.csv:ieee:,
+csvs/scopus.csv:scopus:,
+csvs/wos1-500.txt:scopus:\t
+csvs/wos501-532.txt:scopus:\t

+ 49 - 0
filters/filter.py

@@ -0,0 +1,49 @@
+class Filter(object):
+  
+  def getTitle (self, csvRow):
+    return csvRow[self.getTitleField()]
+  
+  def getAbstract (self, csvRow):
+    return csvRow[self.getAbstractField()]
+  
+  def getAuthors (self, csvRow):
+    return csvRow[self.getAuthorsField()]
+  
+  def getKeywordExtra (self, csvRow):
+    if self.getKeywordExtraField() in csvRow:
+      return csvRow[self.getKeywordExtraField()]
+    else:
+      return ''
+  
+  def getKeyword (self, csvRow):
+    return csvRow[self.getKeywordField()]
+  
+  def getDOI (self, csvRow):
+    return csvRow[self.getDOIField()]
+  
+  def getCSVData (self, csvRow):
+    title = self.getTitle(csvRow)
+    authors = self.getAuthors(csvRow)
+    abstract = self.getAbstract(csvRow)
+    keyword = self.getKeyword(csvRow)
+    doi = self.getDOI(csvRow)
+    keywordExtra = self.getKeywordExtra(csvRow)
+    return [title, abstract, authors, doi, keyword, keywordExtra]
+  
+  def getAbstractField (self):
+    raise NotImplementedError
+  
+  def getTitleField (self):
+    raise NotImplementedError
+  
+  def getAuthorsField (self):
+    raise NotImplementedError
+  
+  def getKeywordField (self):
+    raise NotImplementedError
+  
+  def getKeywordExtraField (self):
+    raise NotImplementedError
+  
+  def getDOIField (self):
+    raise NotImplementedError

+ 21 - 0
filters/ieeeFilter.py

@@ -0,0 +1,21 @@
+from filters.filter import Filter
+
+class IEEEFilter (Filter):
+  
+  def getAbstractField (self):
+    return "Abstract"
+  
+  def getAuthorsField (self):
+    return "Authors"
+  
+  def getDOIField (self):
+    return "DOI"
+  
+  def getTitleField (self):
+    return "Document Title"
+  
+  def getKeywordField (self):
+    return "Author Keywords"
+  
+  def getKeywordExtraField (self):
+    return "IEEE Terms"

+ 21 - 0
filters/scopusFilter.py

@@ -0,0 +1,21 @@
+from filters.filter import Filter
+
+class ScopusFilter (Filter):
+  
+  def getAbstractField (self):
+    return "Abstract"
+  
+  def getAuthorsField (self):
+    return "Authors"
+  
+  def getDOIField (self):
+    return "DOI"
+  
+  def getTitleField (self):
+    return "Title"
+  
+  def getKeywordField (self):
+    return "Author Keywords"
+  
+  def getKeywordExtraField (self):
+    return ""

+ 21 - 0
filters/webScienceFilter.py

@@ -0,0 +1,21 @@
+from filters.filter import Filter
+
+class WebScience (Filter):
+  
+  def getAbstractField (self):
+    return "AB"
+  
+  def getAuthorsField (self):
+    return "AU"
+  
+  def getDOIField (self):
+    return "DI"
+  
+  def getTitleField (self):
+    return "TI"
+  
+  def getKeywordField (self):
+    return "DE"
+  
+  def getKeywordExtraField (self):
+    return "ID"

+ 124 - 0
helpers.py

@@ -0,0 +1,124 @@
+import csv
+import sys
+import os
+import tkinter as tk
+from tkinter import messagebox
+import hashlib
+import pickle
+import filters.ieeeFilter as IEEE, filters.scopusFilter as Scopus, filters.webScienceFilter as WebOfScience
+# titulo, abstract, autores, arquivo&linha, DOI, palavras-chave,palavras-chave extras
+
+FINAL_CSV_HEADERS = ['titulo', 'abstract', 'autores', 'doi', 'keywords','extra_keywords', 'fonte']
+
+def loadFiles (files):
+  loadedFiles = []
+  for file in files:
+    loadedFiles.append((csv.DictReader(open(file['path']), delimiter=file['separator']), file))
+  return loadedFiles
+
+def saveAcceptedCSV (data):
+  file = open('./accepted.csv', mode='w')
+  headers = data['header']
+  writer = csv.writer(file, delimiter=',')
+  writer.writerow(headers)
+  data.pop('header')
+  for row in data.values():
+    writer.writerow(row)
+  file.flush()
+  file.close()
+
+def saveRejectedCSV (data):
+  file = open('./rejected.csv', mode='w')
+  headers = data['header']
+  writer = csv.writer(file, delimiter=',')
+  writer.writerow(headers)
+  data.pop('header')
+  for row in data.values():
+    writer.writerow(row)
+  file.flush()
+  file.close()
+
+def writeFinalLog (data):
+  file = open("./log.txt", mode='w')
+  file.write("accepted: {0}\nrejected: {1}\nduplicated: {2}\n".format(data['accepted'],data['rejected'],data['duplicate']))
+  file.flush()
+  file.close()
+
+def removeStateFile ():
+  try:
+    os.remove('./.csvstate')
+  except Exception:
+    pass
+
+def saveState (data):
+  file = open('./.csvstate', mode='wb')
+  pickle.dump(data, file)
+  file.close()
+
+def loadState (root):
+  try:
+    file = open('./.csvstate', mode='rb')
+    answer = tk.messagebox.askyesno("State lading","Load last session state?")
+    if answer:
+      data = pickle.load(file)
+      file.close()
+      return data
+  except Exception:
+    pass
+  return {'file_index':0, 'row_index':0, 'accepted':0, 'rejected':0, 'duplicate': 0}
+
+def loadConfigFile ():
+  files = list()
+  try:
+    file = open('./csvconfig.txt')
+    rawData = file.read()
+    lines = rawData.split('\n')
+    for line in lines:
+      parameters = line.split(':')
+      separator = parameters[2].encode('utf-8').decode("unicode_escape")
+      fileConfig = {'path': parameters[0], 'filter': parameters[1], 'separator': separator}
+      files.append(fileConfig)
+    file.close()
+    return files
+  except FileNotFoundError:
+    return list()
+
+def getFilter (file):
+  if file['filter'] == 'ieee':
+    return IEEE.IEEEFilter()
+  elif file['filter'] == 'scopus':
+    return Scopus.ScopusFilter()
+  elif file['filter'] == 'webscience':
+    return WebOfScience.WebScience()
+  else:
+    raise Exception('Undefined filter '+file['filter'])
+
+def restoreAcceptedCSV ():
+  try:
+    file = open('./accepted.csv')
+    rows = list(csv.reader(file))
+    data = {}
+    if len(rows) == 0:
+      return data
+    data['header'] = rows[0]
+    for i in range(1,len(rows)):
+      digest = hashlib.sha256(str.encode(rows[i][0])).hexdigest()
+      data[digest] = rows[i]
+    return data
+  except FileNotFoundError:
+    return {}
+
+def restoreRejectedCSV ():
+  try:
+    file = open('./rejected.csv')
+    rows = list(csv.reader(file))
+    data = {}
+    if len(rows) == 0:
+      return data
+    data['header'] = rows[0]
+    for i in range(1,len(rows)):
+      digest = hashlib.sha256(str.encode(rows[i][0])).hexdigest()
+      data[digest] = rows[i]
+    return data
+  except FileNotFoundError:
+    return {}

+ 183 - 0
main.py

@@ -0,0 +1,183 @@
+import hashlib
+import sys
+from tkinter import *
+
+import helpers
+
+root = Tk()
+titleLabel = StringVar()
+text = StringVar()
+filesInfo = None
+csvFiles = None
+state = None
+acceptedDataCSV = None
+rejectedDataCSV = None
+
+def findDuplicate (hashDict, title):
+  if title in hashDict:
+    return True
+  else:
+    return False
+
+def acceptPaper (file, csvRow, index):
+  global state
+  global acceptedDataCSV
+  fileFilter = helpers.getFilter(file)
+  data = fileFilter.getCSVData(csvRow)
+  digest = hashlib.sha256(str.encode(fileFilter.getTitle(csvRow))).hexdigest()
+  duplicate = findDuplicate(rejectedDataCSV, digest) or findDuplicate(acceptedDataCSV, digest)
+  if duplicate:
+    state['duplihttps://mail.google.com/mail/u/0/#inboxcate'] += 1
+  else:
+    data.append("{0} - {1}".format(file['path'],index))
+    acceptedDataCSV[digest] = data
+    state['accepted'] += 1
+  return
+
+def rejectPaper (file, csvRow, index):
+  global rejectedDataCSV
+  global state
+  fileFilter = helpers.getFilter(file)
+  data = fileFilter.getCSVData(csvRow)
+  digest = hashlib.sha256(str.encode(fileFilter.getTitle(csvRow))).hexdigest()
+  duplicate = findDuplicate(rejectedDataCSV, digest) or findDuplicate(acceptedDataCSV, digest)
+  if duplicate:
+    state['duplicate'] += 1
+  else:
+    data.append("{0} - {1}".format(file['path'],index))
+    rejectedDataCSV[digest] = data
+    state['rejected'] += 1
+  return
+
+def rejectButtonHandler (*arg):
+  global state
+  global csvFiles
+  index = state['row_index']
+  fileIndex = state['file_index']
+  fileTuple = csvFiles[fileIndex]
+  rejectPaper(fileTuple[1], fileTuple[0][index], index)
+  nextPaper()
+  return
+
+def acceptButtonHandler (*arg):
+  global state
+  global csvFiles
+  index = state['row_index']
+  fileIndex = state['file_index']
+  fileTuple = csvFiles[fileIndex]
+  acceptPaper(fileTuple[1], fileTuple[0][index], index)
+  nextPaper()
+  return
+
+
+def updateAndClear (textField, *args):
+  textField.config(state=NORMAL)
+  textField.delete('1.0', END)
+  textField.insert(INSERT, text.get())
+  textField.tag_add("center", '1.0', END)
+  textField.config(state=DISABLED)
+
+def loadFiles ():
+  global filesInfo
+  global csvFiles
+  global state
+  global root
+  global acceptedDataCSV
+  global rejectedDataCSV
+  filesInfo = helpers.loadConfigFile()
+  if len(filesInfo) == 0:
+    sys.exit("csvconfig.txt not found. You need this file to run the program")
+  state = helpers.loadState(root)
+  acceptedDataCSV = helpers.restoreAcceptedCSV() #load default file, if present append else create new one
+  rejectedDataCSV = helpers.restoreRejectedCSV()
+  if len(acceptedDataCSV) == 0:
+      acceptedDataCSV['header'] = helpers.FINAL_CSV_HEADERS
+  if len(rejectedDataCSV) == 0:
+    rejectedDataCSV['header'] = helpers.FINAL_CSV_HEADERS
+  csvFiles = [(list(f[0]), f[1]) for f in helpers.loadFiles(filesInfo)]
+  setPaperFromState()
+
+def setPaperFromState ():
+  global titleLabel
+  global text
+  fileIndex = state['file_index']
+  if fileIndex >= len(filesInfo):
+    return #finished processing
+  fileList = csvFiles[fileIndex][0]
+  index = state['row_index']
+  if index >= len(fileList):
+    state['file_index'] += 1
+    state['row_index'] = 0
+    setPaperFromState()
+  else:
+    file = fileList[index]
+    fileFilter = helpers.getFilter(csvFiles[fileIndex][1])
+    title = fileFilter.getTitle(file)
+    abstract = fileFilter.getAbstract(file)
+    titleLabel.set(title)
+    text.set(abstract)
+
+def nextPaper ():
+  global titleLabel
+  global text
+  global root
+  fileIndex = state['file_index']
+  if fileIndex >= len(filesInfo):
+    helpers.removeStateFile()
+    helpers.writeFinalLog(state)
+    helpers.saveAcceptedCSV(acceptedDataCSV)
+    helpers.saveRejectedCSV(rejectedDataCSV)
+    root.destroy()#acabou, fecha essa porra
+    return
+  fileList = csvFiles[fileIndex][0]
+  index = state['row_index'] = state['row_index'] + 1
+  if index >= len(fileList):
+    state['file_index'] += 1
+    state['row_index'] = -1
+    nextPaper()
+  else:
+    file = fileList[index]
+    fileFilter = helpers.getFilter(csvFiles[fileIndex][1])
+    title = fileFilter.getTitle(file)
+    abstract = fileFilter.getAbstract(file)
+    titleLabel.set(title)
+    text.set(abstract)
+
+def onClosing ():
+  global state
+  global root
+  global acceptedDataCSV
+  global rejectedDataCSV
+  helpers.saveState(state)
+  helpers.saveAcceptedCSV(acceptedDataCSV)
+  helpers.saveRejectedCSV(rejectedDataCSV)
+  root.destroy()
+
+
+def main ():
+  global root
+  root.title('Reviewer')
+  root.geometry('800x600')
+  topFrame = Frame(root)
+  bottomFrame = Frame(root)
+  bottomFrame.pack(side=BOTTOM)
+  topFrame.pack(side=TOP, fill=BOTH, expand=True)
+  label = Label(root, textvariable=titleLabel, relief=RAISED)
+  label.pack(in_=topFrame, fill=BOTH, side=TOP)
+  textField = Text(root)
+  textField.tag_configure("center", wrap=WORD)
+  textField.pack(in_=topFrame, fill=BOTH, side=TOP)
+  accept = Button(root, text ="Accept Paper", command = acceptButtonHandler)
+  root.bind('<Right>', lambda e: acceptButtonHandler())
+  accept.pack(in_=bottomFrame, side=LEFT)
+  reject = Button(root, text ="Reject Paper", command = rejectButtonHandler)
+  root.bind('<Down>', lambda e: rejectButtonHandler())
+  reject.pack(in_=bottomFrame, side=LEFT)
+  textField.insert(INSERT, text.get())
+  text.trace('w', lambda *arg: updateAndClear(textField))
+  textField.config(state=DISABLED)
+  root.protocol("WM_DELETE_WINDOW", onClosing)
+  root.mainloop()
+
+loadFiles()
+main()