__copyright__ = "Copyright (c) 2021"
__author__ = "Rakha Asyrofi"
__date__ = "2021-10-08:18:07:39"

# -*- coding: utf-8 -*-
"""modul_relasi.ipynb
Author Rakha Asyrofi / 05111950010038

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1h6HKNeALV8bXjrxWB0Jn0ztHtLv2cXz8
"""

"""# Modul3: pencarian relasi"""

# !pip install -U pywsd
# !pip install -U wn==0.0.23

import pandas as pd
import numpy as np
from spacy.lang.en import English
from spacy.tokenizer import Tokenizer
from pywsd import disambiguate
from pywsd.similarity import similarity_by_path
from tabulate import tabulate
from tqdm.auto import tqdm
from time import sleep, time

# template class ucdReq
class ucdReq:

  #inicsialisasi
  def __init__(self, data_aksi_aktor, tabel_usecase):
    self.aksi_aktor = data_aksi_aktor
    self.dt_usecase = tabel_usecase

  def progressBar(self, data):
      pbar = tqdm(iterable= range(0, len(data)), leave= False, desc= 'loading..', unit= 'synsets')
      for i in pbar:
          sleep(0.1)
          pbar.update(1)
      return pbar.close()

  def progressBarDataFrame(self, data):
      return data.progress_apply(lambda x: x)

  def fulldataset(self, inputData):
      xl = pd.ExcelFile(self.aksi_aktor)
      dfs = {sh:xl.parse(sh) for sh in xl.sheet_names}
      kalimat = dfs[inputData]
      kalimat_semua = kalimat.head(len(kalimat))
      return kalimat_semua

  def fulldataset_xmi(self, inputXMI):
      xl = pd.ExcelFile(self.dt_usecase)
      dfs = {sh:xl.parse(sh) for sh in xl.sheet_names}
      kalimat = dfs[inputXMI]
      kalimat_semua = kalimat.head(len(kalimat))
      return kalimat_semua

  def preprocessing(self):
    xl = pd.ExcelFile(self.aksi_aktor)
    for sh in xl.sheet_names:
      df = xl.parse(sh)
      print('Processing: [{}] ...'.format(sh))
      print(df.head())

  def synset_word(self, data): # pencarian synset
    try:
      nlp = English()
      # tokenizer = nlp.Defaults.create_tokenizer(nlp)
      tokenizer = tokenizer = Tokenizer(nlp.vocab)
      num_token = [token.text for token in tokenizer(data)]
      word = [disambiguate(x) for x in num_token]
      wordsynset = [[n[1] for n in y if n[1] is not None] for y in word]
      final_synset = [val[0] for val in wordsynset if len(val) > 0]
      # ucdReq.progressBar(self, final_synset)
      return final_synset

    except OSError as err:
        print("OS error: {0}".format(err))

  def wsd_greedy(self, s1, s2): # kombinasi algoritma wsd dan greedy
    try:
      scores = [[x for x in [similarity_by_path(i1, i2, option= 'wup') for i2 in s2] if x is not None] for i1 in s1]
      flt_scores = [val for val in scores if len(val) > 0]
      ucdReq.progressBar(self, flt_scores) # visualisasi proses
      list_wsd = [np.max(num) for num in flt_scores]
      dt = (sorted(list_wsd, reverse=True))
      dt_value = dt[:len(dt)-1]
      kalkulasi = 2 * sum(dt_value) / ((len(flt_scores)) + (len(flt_scores[0])))
      return kalkulasi
    except OSError as err:
        print("OS error: {0}".format(err))

  def similaritas_doc(self, doc1, doc2): # pencarian kesmaaan dokumen
    try:
      synsets1 = ucdReq.synset_word(self, doc1)
      synsets2 = ucdReq.synset_word(self, doc2)
      kalkulasi_synset = (ucdReq.wsd_greedy(self, synsets1, synsets2) + ucdReq.wsd_greedy(self, synsets2, synsets1)) / 2   
      return kalkulasi_synset
    except OSError as err:
        print("OS error: {0}".format(err))

  def ucdMeasurement(self, keyword1, keyword2): #pengukuran
    try:
      hasil_wsd = [[ucdReq.similaritas_doc(self, num, angka) for angka in keyword2] for num in keyword1]
      wsd_df = pd.DataFrame(hasil_wsd)
      # ucdReq.progressBar(self, wsd_df)
      return wsd_df
    except OSError as err:
        print("OS error: {0}".format(err))

  def change_case(self, word):
      return ''.join([' '+i.lower() if i.isupper() else i for i in word]).lstrip(' ')

  def thresholdvalue(self, threshold, data):
    try:
      dt = data.values >= threshold
      d1 = pd.DataFrame(dt, index= data.index, columns= data.columns)
      mask = d1.isin([True])
      d2 = d1.where(mask, other= 0)
      mask2 = d1.isin([False])
      return d2.where(mask2, other= 1)
    except OSError as err:
        print("OS error: {0}".format(err))



  def __del__(self):
    print ('Destructor called.')

if __name__ == "__main__":
  try:
      # openfile
      t0 = time()
      MyucdReq = ucdReq(data_aksi_aktor= r'data_aksi_aktor.xlsx', tabel_usecase= r'data_xmi.xlsx')
      tabel_freq =  'tabel_freqs' 
      freqs = MyucdReq.fulldataset(inputData= tabel_freq)# data dari txt
      tabel_ucd1 =  'tabel_ucd1' 
      ucd1 = MyucdReq.fulldataset(inputData= tabel_ucd1) # data dari txt
      tabel_ucd2 =  'tabel_ucd2' 
      ucd2 = MyucdReq.fulldataset(inputData= tabel_ucd2) # data dari txt
      namaUsecase =  'tabel_usecase'
      useCaseTable  = MyucdReq.fulldataset_xmi(inputXMI= namaUsecase) # dari xmi


      tbl_1 = MyucdReq.ucdMeasurement(freqs.aksi, ucd1.dropna().aksi)
      tbl_1.columns = ucd1.dropna().usecase
      tbl_1.index = freqs.id
      tbl_1.rename(columns = {'insertMetadata_1':'UC01', 'insertMetadata_2':'UC01',  'insertMetadata_3':'UC01', 'insertMetadata_4':'UC01',  'insertMetadata_5':'UC01',
                              'searchArticle_1':'UC03', 'searchArticle_2':'UC03', 'searchArticle_3':'UC03', 'searchArticle_4':'UC03', 'searchArticle_5':'UC03',    
                              'viewNextResult_1':'UC04', 'viewNextResult_2':'UC04', 'viewNextResult_3':'UC04', 
                              }, inplace = True)
      tqdm.pandas(desc="Data Pengukuran antara functional dan ucd1 (txt)")
      MyucdReq.progressBarDataFrame(tbl_1)
      print(tabulate(tbl_1, headers = 'keys', tablefmt = 'psql'))

      print("\n\n")
      tbl_2 = MyucdReq.ucdMeasurement(freqs.aksi, ucd2.dropna().aksi)
      tbl_2.columns = ucd2.dropna().usecase
      tbl_2.index = freqs.id
      tbl_2.rename(columns = {'searchResearcher_1':'UC02','searchResearcher_2':'UC02', 'searchResearcher_3':'UC02',
                              'orderByRelevancy_1':'UC05', 'orderByRelevancy_2':'UC05','orderByRelevancy_3':'UC05',  
                              'orderByScore_1':'UC06','orderByScore_2':'UC06', 'orderByScore_3':'UC06',
                              'viewDetailResearcher_1':'UC07','viewDetailResearcher_2':'UC07', 'viewDetailResearcher_3':'UC07', 
                              'removeArticle_1':'UC09', 'removeArticle_2':'UC09', 'removeArticle_3':'UC09', 
                              'editProfile_1':'UC08', 'editProfile_2':'UC08',  'editProfile_3':'UC08','editProfile_4':'UC08', 'editProfile_5':'UC08',
                              }, inplace = True)
      tqdm.pandas(desc="Data filter pengukuran maksmimum antara functional terhadap ucd1 dan ucd2 (txt)")
      MyucdReq.progressBarDataFrame(tbl_2)
      print(tabulate(tbl_2, headers = 'keys', tablefmt = 'psql'))

      print("\n\n")
      tbl_3 = pd.concat([tbl_1, tbl_2], axis= 1)
      tbl_3['uc01'] = tbl_3.UC01.values.max(1)
      tbl_3['uc02'] = tbl_3.UC02.values.max(1)
      tbl_3['uc03'] = tbl_3.UC03.values.max(1)
      tbl_3['uc04'] = tbl_3.UC04.values.max(1)
      tbl_3['uc05'] = tbl_3.UC05.values.max(1)
      tbl_3['uc06'] = tbl_3.UC06.values.max(1)
      tbl_3['uc07'] = tbl_3.UC07.values.max(1)
      tbl_3['uc08'] = tbl_3.UC08.values.max(1)
      tbl_3['uc09'] = tbl_3.UC09.values.max(1)
      tbl_3filter = tbl_3.drop(['UC01','UC02', 'UC03', 'UC04', 'UC05', 'UC06', 'UC07', 'UC08', 'UC09'], axis= 1)
      tqdm.pandas(desc="Data filter pengukuran maksmimum antara functional terhadap ucd1 dan ucd2 (txt)")
      MyucdReq.progressBarDataFrame(tbl_3filter)
      print(tabulate(tbl_3filter, headers = 'keys', tablefmt = 'psql'))

      print("\n\n")
      tbl_4 = MyucdReq.thresholdvalue(0.4, tbl_3filter)
      tqdm.pandas(desc="Data hasil relasi antara kebutuhan dan kasus penggunaan (txt)\n")
      MyucdReq.progressBarDataFrame(tbl_4)
      print(tabulate(tbl_4, headers = 'keys', tablefmt = 'psql'))

      # xmi code
      print("\n\n")
      data_ucd = [MyucdReq.change_case(num) for num in useCaseTable.name]
      tbl_1x = MyucdReq.ucdMeasurement(freqs.aksi, data_ucd)
      tbl_1x.index = freqs.id
      tbl_1x.columns = useCaseTable.name
      tbl_1x.rename(columns = {'insertMetadata':'uc01', 'searchArticle':'uc03', 'viewNextResult':'uc04', 
                               'searchResearcher':'uc02', 'orderByRelevancy':'uc05', 'orderByScore':'uc06', 
                              'viewDetailOfResearcher':'uc07', 'removeArticle':'uc09', 'editProfile':'uc08' }, inplace = True)
      print("\n\n")
      tqdm.pandas(desc="Data hasil relasi antara kebutuhan dan kasus penggunaan (xmi)")
      MyucdReq.progressBarDataFrame(tbl_1x)
      print(tabulate(tbl_1x, headers = 'keys', tablefmt = 'psql'))

      print("\n\n")
      tbl_5 = MyucdReq.thresholdvalue(0.3, tbl_1x)
      tqdm.pandas(desc="Data hasil threshold relasi (xmi)\n")
      MyucdReq.progressBarDataFrame(tbl_5)
      print(tabulate(tbl_5, headers = 'keys', tablefmt = 'psql'))

      print("\n\n")
      list_usecase = [num for num in tbl_5.columns]
      # tbl_6 = tbl_4.merge(tbl_5, how= 'inner', left_index= True, right_index= True, on= list_usecase)
      tbl_6 = tbl_4.merge(tbl_5, how= 'inner', on= list_usecase)
      tqdm.pandas(desc="Data hasil join relasi antara kebutuhan dan kasus penggunaan (txt dan xmi)\n")
      MyucdReq.progressBarDataFrame(tbl_6)
      print(tabulate(tbl_6, headers = 'keys', tablefmt = 'psql'))
      
      print("done in %0.3fs." % (time() - t0))
      input('Press ENTER to exit') 

      MyucdReq.__del__()

  except OSError as err:
      print("OS error: {0}".format(err))