Advertisement
mikhailemv

5.2

Dec 17th, 2022
740
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.74 KB | None | 0 0
  1. from re import sub
  2. from csv import reader
  3.  
  4. from prettytable import PrettyTable
  5.  
  6.  
  7. class Salary:
  8.     currency_to_rub = {
  9.         "AZN": 35.68,
  10.         "BYR": 23.91,
  11.         "EUR": 59.90,
  12.         "GEL": 21.74,
  13.         "KGS": 0.76,
  14.         "KZT": 0.13,
  15.         "RUR": 1,
  16.         "UAH": 1.64,
  17.         "USD": 60.66,
  18.         "UZS": 0.0055,
  19.     }
  20.  
  21.     currency_name = {
  22.         'AZN': 'Манаты',
  23.         'BYR': 'Белорусские рубли',
  24.         'EUR': 'Евро',
  25.         'GEL': 'Грузинский лари',
  26.         'KGS': 'Киргизский сом',
  27.         'KZT': 'Тенге',
  28.         'RUR': 'Рубли',
  29.         'UAH': 'Гривны',
  30.         'USD': 'Доллары',
  31.         'UZS': 'Узбекский сум'
  32.     }
  33.  
  34.     def __str__(self) -> str:
  35.         return '{0:,} - {1:,} ({2}) ({3})'.format(self.salary_from,
  36.                                                   self.salary_to,
  37.                                                   Salary.currency_name[self.salary_currency],
  38.                                                   self.salary_gross).replace(',', ' ')
  39.  
  40.     def __init__(self, separate_vacancy: dict) -> None:
  41.         self.salary_to = int(float(separate_vacancy['salary_to']))
  42.         self.salary_from = int(float(separate_vacancy['salary_from']))
  43.         self.salary_currency = separate_vacancy['salary_currency']
  44.         self.salary_gross = 'Без вычета налогов' \
  45.             if separate_vacancy['salary_gross'].lower() == 'true' \
  46.             else 'С вычетом налогов'
  47.         self.salary_average = Salary.currency_to_rub[self.salary_currency] * (self.salary_from + self.salary_to) / 2
  48.  
  49.  
  50. class Vacancy:
  51.     headline_naming = ['index',
  52.                        'name',
  53.                        'description',
  54.                        'key_skills',
  55.                        'experience_id',
  56.                        'premium',
  57.                        'employer_name',
  58.                        'salary',
  59.                        'area_name',
  60.                        'published_at']
  61.  
  62.     specific_weights = \
  63.         {
  64.             'Нет опыта': 1,
  65.             'От 1 года до 3 лет': 2,
  66.             'От 3 до 6 лет': 3,
  67.             'Более 6 лет': 4
  68.         }
  69.  
  70.     work_experience_ru = \
  71.         {
  72.             'noExperience': 'Нет опыта',
  73.             'between1And3': 'От 1 года до 3 лет',
  74.             'between3And6': 'От 3 до 6 лет',
  75.             'moreThan6': 'Более 6 лет',
  76.         }
  77.  
  78.     def __init__(self, separate_vacancy: dict) -> None:
  79.         self.index = 0
  80.         self.name = self.get_html_tag_free_string(separate_vacancy['name'])
  81.         self.description = self.get_short_string(self.get_html_tag_free_string(separate_vacancy['description']))
  82.         self.skills = separate_vacancy['key_skills'].split('\n')
  83.         self.key_skills = self.get_short_string(separate_vacancy['key_skills'])
  84.         self.skills_length = len(self.skills)
  85.         self.experience_id = self.work_experience_ru[separate_vacancy['experience_id']]
  86.         self.premium = 'Да' \
  87.             if separate_vacancy['premium'].lower() == 'true' \
  88.             else 'Нет'
  89.         self.employer_name = separate_vacancy['employer_name']
  90.         self.salary_class = Salary(separate_vacancy)
  91.         self.salary = str(self.salary_class)
  92.         self.area_name = separate_vacancy['area_name']
  93.         self.published = separate_vacancy['published_at']
  94.         self.published_at = '{0[2]}.{0[1]}.{0[0]}'.format(separate_vacancy['published_at'][:10].split('-'))
  95.  
  96.     def drag_current_object_to_list(self) -> list:
  97.         return [getattr(self, key) for key in self.headline_naming]
  98.  
  99.     @property
  100.     def salary_average(self):
  101.         return self.salary_class.salary_average
  102.  
  103.     @property
  104.     def salary_currency(self):
  105.         return self.salary_class.salary_currency
  106.  
  107.     @property
  108.     def salary_from(self):
  109.         return self.salary_class.salary_from
  110.  
  111.     @property
  112.     def salary_to(self):
  113.         return self.salary_class.salary_to
  114.  
  115.     @property
  116.     def experience_weight(self):
  117.         return self.specific_weights[self.experience_id]
  118.  
  119.     @staticmethod
  120.     def get_short_string(string: str) -> str:
  121.         if len(string) <= 100:
  122.             return string
  123.         return string[:100] + '...'
  124.  
  125.     @staticmethod
  126.     def get_html_tag_free_string(string: str) -> str:
  127.         result = sub(r'<.*?>', '', string)
  128.         result = sub(r'\s+', ' ', result)
  129.         return result.strip()
  130.  
  131.  
  132. class DataSet:
  133.     dictionary_translator = \
  134.         {
  135.             'Премиум-вакансия': 'premium',
  136.             'Идентификатор валюты оклада': 'salary_currency',
  137.             'Название': 'name',
  138.             'Название региона': 'area_name',
  139.             'Компания': 'employer_name',
  140.             'Описание': 'description',
  141.             'Навыки': 'skills_length',
  142.             'Оклад': 'salary_average',
  143.             'Дата публикации вакансии': 'published',
  144.             'Опыт работы': 'experience_weight',
  145.         }
  146.  
  147.     lambda_sorter_dictionary = \
  148.         {
  149.             'Идентификатор валюты оклада': lambda vacancy, value:
  150.             Salary.currency_name[vacancy.salary_currency] == value,
  151.             'Название': lambda vacancy, value: vacancy.name == value,
  152.             'Название региона': lambda vacancy, value: vacancy.area_name == value,
  153.             'Компания': lambda vacancy, value: vacancy.employer_name == value,
  154.             'Навыки': lambda vacancy, value: all([skill in vacancy.skills for skill in value.split(', ')]),
  155.             'Оклад': lambda vacancy, value: vacancy.salary_from <= float(value) <= vacancy.salary_to,
  156.             'Дата публикации вакансии': lambda vacancy, value: vacancy.published_at == value,
  157.             'Опыт работы': lambda vacancy, value: vacancy.experience_id == value,
  158.             'Премиум-вакансия': lambda vacancy, value: vacancy.premium == value,
  159.         }
  160.  
  161.     def __init__(self,
  162.                  naming,
  163.                  filter_measure,
  164.                  measure_to_sort,
  165.                  sort_factor_to_reverse,
  166.                  sort_factor_to_range):
  167.         self.sort_factor_to_reverse = sort_factor_to_reverse
  168.         self.sort_factor_to_range = sort_factor_to_range
  169.         self.naming = naming
  170.         self.filter_measure = filter_measure
  171.         self.measure_to_sort = measure_to_sort
  172.         self.vacancies_list = list()
  173.  
  174.     def for_ranging(self) -> None:
  175.         needed_vacancies_list = list()
  176.         for index, vacancy in enumerate(self.vacancies_list):
  177.             if (len(self.sort_factor_to_range) > 1 and
  178.                 self.sort_factor_to_range[0] <= index < self.sort_factor_to_range[1]) or \
  179.                     (len(self.sort_factor_to_range) == 1 and
  180.                      self.sort_factor_to_range[0] <= index) or \
  181.                     len(self.sort_factor_to_range) == 0:
  182.                 needed_vacancies_list.append(vacancy)
  183.                 vacancy.index = index + 1
  184.         self.vacancies_list = needed_vacancies_list
  185.  
  186.     def get_rows_list(self) -> list:
  187.         return [current_vacancy.drag_current_object_to_list()
  188.                 for current_vacancy in self.vacancies_list]
  189.  
  190.     def to_sort_rows_list(self) -> None:
  191.         if self.measure_to_sort != '':
  192.             self.vacancies_list.sort(key=lambda vacancy: getattr(vacancy,
  193.                                                                  DataSet.dictionary_translator[self.measure_to_sort]),
  194.                                      reverse=self.sort_factor_to_reverse)
  195.         elif self.sort_factor_to_reverse and self.measure_to_sort == '':
  196.             self.vacancies_list.reverse()
  197.  
  198.     def to_filter_rows(self):
  199.         if len(self.filter_measure) == 0:
  200.             return
  201.         self.vacancies_list = list(filter(lambda current_vacancy:
  202.                                           self.lambda_sorter_dictionary[
  203.                                               self.filter_measure[0]](current_vacancy,
  204.                                                                       self.filter_measure[1]), self.vacancies_list))
  205.  
  206.     def csv_reader(self) -> None:
  207.         header = list()
  208.         with open(self.naming, mode='r', encoding='utf-8-sig') as file:
  209.             csv_reader = reader(file)
  210.             for index, row_value in enumerate(csv_reader):
  211.                 if index == 0:
  212.                     header = row_value
  213.                     csv_header_length = len(row_value)
  214.                 elif '' not in row_value and \
  215.                         len(row_value) == csv_header_length:
  216.                     self.vacancies_list.append(Vacancy(dict(zip(header, row_value))))
  217.         if len(self.vacancies_list) == 0:
  218.             if len(header) == 0:
  219.                 print('Пустой файл')
  220.             else:
  221.                 print('Нет данных')
  222.             exit()
  223.  
  224.  
  225. class InputConnect:
  226.     headline_list = ['№',
  227.                      'Название',
  228.                      'Описание',
  229.                      'Навыки',
  230.                      'Опыт работы',
  231.                      'Премиум-вакансия',
  232.                      'Компания',
  233.                      'Оклад',
  234.                      'Название региона',
  235.                      'Дата публикации вакансии']
  236.  
  237.     def __init__(self):
  238.         self.errors_list = list()
  239.         self.file_name = input('Введите название файла: ')
  240.         self.filter_param = self.to_parse_for_filtering(input('Введите параметр фильтрации: '))
  241.         self.sort_param = self.to_parse_sort_measure(input('Введите параметр сортировки: '))
  242.         self.sort_reverse = self.to_parsing_sort_reverse(input('Обратный порядок сортировки (Да / Нет): '))
  243.         self.sort_range = self.to_parse_sort_ranging(input('Введите диапазон вывода: '))
  244.         self.table_fields = self.to_parse_table_areas(input('Введите требуемые столбцы: '))
  245.  
  246.         if len(self.errors_list) != 0:
  247.             print(self.errors_list[0])
  248.             exit()
  249.  
  250.         data_set = DataSet(self.file_name,
  251.                            self.filter_param,
  252.                            self.sort_param,
  253.                            self.sort_reverse,
  254.                            self.sort_range)
  255.        
  256.         data_set.csv_reader()
  257.         data_set.to_filter_rows()
  258.         data_set.to_sort_rows_list()
  259.         data_set.for_ranging()
  260.  
  261.         rows_list = data_set.get_rows_list()
  262.  
  263.         if len(rows_list) == 0:
  264.             print('Ничего не найдено')
  265.         else:
  266.             table = PrettyTable(align='l',
  267.                                 field_names=InputConnect.headline_list,
  268.                                 max_width=20,
  269.                                 hrules=1)
  270.             table.add_rows(rows_list)
  271.             print(table.get_string(fields=self.table_fields))
  272.  
  273.     def to_parse_for_filtering(self, filter_value):
  274.         if filter_value == '':
  275.             return []
  276.  
  277.         if ': ' not in filter_value:
  278.             self.errors_list.append('Формат ввода некорректен')
  279.             return []
  280.  
  281.         filter_param = filter_value.split(': ')
  282.  
  283.         if filter_param[0] not in list(DataSet.lambda_sorter_dictionary.keys()):
  284.             self.errors_list.append('Параметр поиска некорректен')
  285.             return []
  286.  
  287.         return filter_param
  288.  
  289.     @staticmethod
  290.     def to_parse_table_areas(table_areas):
  291.         if table_areas == '':
  292.             return InputConnect.headline_list
  293.         return ['№'] + [vacancy for vacancy in table_areas.split(', ')
  294.                         if vacancy in InputConnect.headline_list]
  295.    
  296.     @staticmethod
  297.     def to_parse_sort_ranging(sort_for_ranging):
  298.         if sort_for_ranging == '':
  299.             return list()
  300.         return [int(limit) - 1 for limit in sort_for_ranging.split()]
  301.  
  302.     def to_parse_sort_measure(self, sort_measure):
  303.         if sort_measure not in InputConnect.headline_list + ['']:
  304.             self.errors_list.append('Параметр сортировки некорректен')
  305.         return sort_measure
  306.  
  307.     def to_parsing_sort_reverse(self, sort_for_reversing):
  308.         if sort_for_reversing not in ('', 'Да', 'Нет'):
  309.             self.errors_list.append('Порядок сортировки задан некорректно')
  310.  
  311.         return True if sort_for_reversing == 'Да' else False
  312.  
  313.  
  314. if __name__ == '__main__':
  315.     InputConnect()
  316.    
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement