Skip to content
This repository has been archived by the owner on Jun 27, 2019. It is now read-only.

2355 - 2 #243

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions 2355/2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
## Для работы данной программы вам понадобиться:
* Установить ruby на свой ПК
* Установить gem "russian-obscenity".
Для этого воспользуйтесь командой ``gem install russian_obscenity``
* Установить gem "terminal-table"
Для этого воспользуйтесь командой ``gem install terminal-table``
* Скачать данную программу. Для этого нажмите зеленую кпопку __Clone or download__ и выберете __Download_ZIP__.
После этого распакуйте архив в любую удобную папку.
* Скачайть архив с текстами баттлов по данной [ссылке](https://yadi.sk/d/uz-52CQP3ZWCtE).
После этого распакуйте архив в папку с программой.
## Инструкция по применению

Откройте папку с программой в консоли. Запустить файл __main.rb__ командой __ruby main.rb__, добавив в конце записи необходимые команды.
Список доступных команд:
* __--top-bad-words=__
* __--top-words=__
* __--name=__

### Команда __--top-bad-words=__

Использование данной команды приводит к тому, что на экране выводится топ исполнителей, в текста баттлов которых входит наибольшее количество нецензурных выражений. Принимает целочисленные агрументы и выводит столько исполнителей, сколько запросил пользователь. По умолчанию(если аргументы не были переданы) выводит только самого нецензурного исполнителя. Также в виде таблицы выводит данные о количестве поединков(баттлов), среднее количество нецензурных слов в поединке и среднее количество слов в раунде.

Пример работы программы.

```
ruby main.rb --top-bad-words=6

+--------------------------+--------------+-------------------------+---------------------+----------------------+
| Леха Медь | 3 баттла(ов) | 276 нецензурных слов(а) | 92 слов(а) на баттл | 626 слов(а) в раунде |
| Rickey F | 6 баттла(ов) | 268 нецензурных слов(а) | 44 слов(а) на баттл | 541 слов(а) в раунде |
| Хип-хоп одинокой старухи | 3 баттла(ов) | 237 нецензурных слов(а) | 79 слов(а) на баттл | 620 слов(а) в раунде |
| Букер | 4 баттла(ов) | 162 нецензурных слов(а) | 40 слов(а) на баттл | 322 слов(а) в раунде |
| Эмио Афишл | 2 баттла(ов) | 155 нецензурных слов(а) | 77 слов(а) на баттл | 574 слов(а) в раунде |
+--------------------------+--------------+-------------------------+---------------------+----------------------+


```

### Команды __--top-words=__ и __--name=__

Данные команды используются вместе и их исполнение приводит к тому, что на экране выводится топ наиболее часто используемых слов заданного исполнителя.
Команда __--top-words=__ принимает целочисленные аргументы и по умолчанию имеет параметр 30, т.е. выводится топ-30 наиболее часто используемых слов.
Команда __--name=__ принимает строковые данные и является обязательной для заполнения, т.к. при отсутствии агрументов выдает ошибку. Также при отсутствии заданного исполнителя в списке баттлеров для анализа, программа выдаст список доступных исполнителей.

Пример работы программы.

```

ruby main.rb --top-words=10 --name=Толик

Рэпер Толик не известен мне. Зато мне известны:
Гнойный
Oxxxymiron
Галат
...

ruby main.rb --top-words=5 --name=Oxxxymiron

просто - 32 раз(а)
рэп - 21 раз(а)
быть - 17 раз(а)
ты, - 16 раз(а)
против - 15 раз(а)
```

12 changes: 12 additions & 0 deletions 2355/2/app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require './first_level.rb'
require './second_level.rb'
require 'optparse'

OptionParser.new do |opts|
opts.on('--top-bad-words=') { |bad| FirstLevel.new(bad).print_table }
opts.on('--top-words=') do |most|
opts.on('--name=') do |battler_name|
SecondLevel.new(most, battler_name).name_check
end
end
end.parse!
10 changes: 10 additions & 0 deletions 2355/2/battle.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This class describes battle
class Battle
attr_reader :file, :words_count

def initialize(name, number)
@name = name
@file = File.new("./rap-battles/#{name}/#{number}")
@words_count = File.readlines("./rap-battles/#{name}/#{number}").join.split.length
end
end
32 changes: 32 additions & 0 deletions 2355/2/first_level.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require './top_bad_words.rb'
require 'terminal-table'

# This class is needed for second level of task
class FirstLevel
def initialize(bad)
@bad = !bad.empty? ? bad.to_i : 1
@first_level = TopBadWords.new
end

def line(value, elem, table)
table << [elem, Rapper.new(elem).battle_count.to_s + ' баттла(ов)',
value[1].to_s + ' нецензурных слов(а)',
@first_level.obscenity_per_battle(elem).to_s + ' слов(а) на баттл',
@first_level.words_per_round(elem).to_s + ' слов(а) в раунде']
end

def table_content(table)
@bad.times do |index|
value = @first_level.top_obscenity_check[index]
elem = value[0]
line(value, elem, table)
end
end

def print_table
table = Terminal::Table.new do |tb|
table_content(tb)
end
puts table
end
end
63 changes: 63 additions & 0 deletions 2355/2/obscenity.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require 'russian_obscenity'
require './rapper.rb'
require './battle.rb'

# This class is needed to find and collect all obscenity from text files for one rapper
class Obscenity
attr_reader :rapper

def initialize(name)
@rapper = Rapper.new(name)
@mistakes = []
end

def initialize_mistakes
File.new('./mistakes').each { |line| @mistakes << line.delete("\n") }
end

def delete_mistakes_from_stars(line)
line.split.each do |word|
@rapper.obscenity << word if word =~ /.*\*.*[А-Яа-я.,]$/
end
end

def check_each_battle_for_star(number)
Battle.new(@rapper.name, number).file.each do |line|
delete_mistakes_from_stars(line)
end
end

def first_check
1.upto(@rapper.battle_count) do |number|
check_each_battle_for_star(number)
end
end

def delete_mistakes_from_rus_obs(word)
@mistakes.each { |mis| @rapper.obscenity << word unless mis.casecmp(word) }
end

def rus_obs_line(line)
RussianObscenity.find(line).each do |word|
delete_mistakes_from_rus_obs(word)
end
end

def check_each_battle_for_rus_obs(number)
Battle.new(@rapper.name, number).file.each do |line|
rus_obs_line(line)
end
end

def check_rus_obs
1.upto(@rapper.battle_count) do |number|
check_each_battle_for_rus_obs(number)
end
end

def check_battles_for_obscenity
initialize_mistakes
first_check
check_rus_obs
end
end
11 changes: 11 additions & 0 deletions 2355/2/rapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This class describes rapper
class Rapper
attr_reader :name, :battle_count, :obscenity, :favourite_words

def initialize(name)
@name = name
@battle_count = Dir[File.join("./rap-battles/#{name}/", '**', '*')].count { |file| File.file?(file) }
@obscenity = []
@favourite_words = {}
end
end
33 changes: 33 additions & 0 deletions 2355/2/second_level.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require './top_bad_words.rb'
require './top_words.rb'
require './rapper.rb'

# This class is needed for second level of task
class SecondLevel
def initialize(most = 30, name = 'None')
@most = !most.empty? ? most.to_i : 30
@name = name
@second_level = TopWord.new(name)
@check = TopBadWords.new
end

def print_top_words
@second_level.ready_top_words
@second_level.res(@most)
end

def battlers_list
@check.battlers_names
@check.battlers
end

def name_check
battlers = battlers_list
if !battlers.include?(@name)
puts 'Я не знаю рэпера ' + @name + ', но знаю таких: '
battlers.each { |battler| puts battler }
else
print_top_words
end
end
end
44 changes: 44 additions & 0 deletions 2355/2/top_bad_words.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require './obscenity.rb'

# This class is needed for first level of Task 2
class TopBadWords
attr_reader :battlers, :top_obscenity

def initialize
@battlers = []
@top_obscenity = {}
end

def battlers_names
File.new('./battlers').each { |line| @battlers << line.delete("\n") }
end

# I don't know how don't use "check." twice
# This method smells of :reek:FeatureEnvy
def top_obscenity_values(check, name)
check.check_battles_for_obscenity
@top_obscenity[name] = check.rapper.obscenity.size
end

def top_obscenity_check
battlers_names
@battlers.each { |name| top_obscenity_values(Obscenity.new(name), name) }
(@top_obscenity.sort_by { |_key, val| val }).reverse
end

def obscenity_per_battle(name)
battler = Rapper.new(name)
@top_obscenity[name] / battler.battle_count
end

# This method is needed in TopBadWords class, so it doesn't depend on instance state
# This method smells of :reek:UtilityFunction
def words_per_round(name, words = 0)
battler = Rapper.new(name)
count = battler.battle_count
1.upto(count) do |number|
words += Battle.new(battler.name, number).words_count
end
words / (count * 3)
end
end
60 changes: 60 additions & 0 deletions 2355/2/top_words.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require './rapper.rb'
require './battle.rb'

# This class is needed to find most popular words from text files
class TopWord
attr_reader :battler

def initialize(name)
@battler = Rapper.new(name)
@pretexts = []
@words = []
@hash = @battler.favourite_words
end

def clear_words(line)
line.split.each do |word|
word = word.delete '.', ',', '?»', '&quot', '!', ';'
@words << word
end
end

def check_words_in_text(number)
Battle.new(@battler.name, number).file.each do |line|
clear_words(line)
end
end

def check_all_words
1.upto(@battler.battle_count) do |number|
check_words_in_text(number)
end
end

def pretexts_value
File.new('./pretexts').each { |word| @pretexts << word.delete("\n") }
end

def top_words_counter
while @words.any?
check = @words.first
@hash[check] = 0
@words.each { |word| @hash[check] += 1 if word == check && [email protected]?(word) }
@words.delete(check)
end
end

def ready_top_words
check_all_words
pretexts_value
top_words_counter
end

def res(value)
most_words = (@hash.sort_by { |_key, val| val }).reverse
0.upto(value - 1) do |index|
word = most_words[index]
puts word[0] + ' - ' + word[1].to_s + ' раз(а)'
end
end
end