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

Commit

Permalink
Merge pull request #231 from leshkacore/hw2
Browse files Browse the repository at this point in the history
2333-2
  • Loading branch information
allomov committed Jul 26, 2018
2 parents e7fb197 + 8ee62c8 commit 934ca6e
Show file tree
Hide file tree
Showing 16 changed files with 288 additions and 0 deletions.
9 changes: 9 additions & 0 deletions 2333/2/Gemfile
@@ -0,0 +1,9 @@
source 'https://rubygems.org'

gem 'json'
gem 'russian_obscenity'
gem 'terminal-table'

group :development do
gem 'pry'
end
25 changes: 25 additions & 0 deletions 2333/2/Gemfile.lock
@@ -0,0 +1,25 @@
GEM
remote: https://rubygems.org/
specs:
coderay (1.1.2)
json (2.1.0)
method_source (0.9.0)
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
russian_obscenity (0.0.1)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
unicode-display_width (1.4.0)

PLATFORMS
ruby

DEPENDENCIES
json
pry
russian_obscenity
terminal-table

BUNDLED WITH
1.16.1
24 changes: 24 additions & 0 deletions 2333/2/README.md
@@ -0,0 +1,24 @@
### О программе
Приложение представляет собой консольную утилиту для анализа, которая принимает в себя различные аргументы. В зависимости от них, поведение приложения меняется и выдает различные данные.

### Аргументы

- **-top-bad-words=** - Параметр, с помощью которого задается количество рэперов для вывода.
- **--name=** - Параметр, с помощью которого задается имя рэпера, для которого будет выведен его топ популярных слов.
- **-top-words=** - Параметр, с помощью которого задается количество популярных слов для вывода.

### Примеры вызова программы:
```sh
$ ruby versus.rb --top-bad-words=3
```
Результатом вызова будет список из трёх рэперов с их статистикой.

```sh
$ ruby versus.rb --top-words=15 --name=Oxxxymiron
```
Результатом вызова будет список из 15-ти самых популярных слов Oxxxymiron'a.

```sh
$ ruby versus.rb --top-words=55 --name=Имя
```
Результатом вызова будет сообщение о том, что программа не знает данного имени, и список известных имен.
1 change: 1 addition & 0 deletions 2333/2/data.json

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions 2333/2/libs/parameters_parser.rb
@@ -0,0 +1,16 @@
require 'optparse'

# Class, that parse command line arguments
class ParametersParser
# :reek:TooManyStatements
# :reek:NestedIterators
def self.parse
@options ||= {}
OptionParser.new do |opts|
opts.on('--top-bad-words=', '') { |value| @options[:top_bad_words] = value }
opts.on('--top-words=', '') { |value| @options[:top_words] = value }
opts.on('--name=', '') { |value| @options[:name] = value }
end.parse!
@options
end
end
38 changes: 38 additions & 0 deletions 2333/2/libs/rapper.rb
@@ -0,0 +1,38 @@
# class Rapper
class Rapper
attr_reader :name, :battles
ROUNDS_ON_BATTLE = 3

def initialize(name, battles)
@name = name
@battles = battles
RussianObscenity.dictionary = [:default, './my_dictionary.yml']
end

def number_of_bad_words
@number_of_bad_words ||= unique_bad_words.map { |word| battles_words.count(word) }.reduce(:+)
end

def battles_words
@battles_words ||= @battles.join(' ').split(/[^[а-яА-Я*ёЁa-zA-Z]]+/)
end

def bad_words_on_battle
(number_of_bad_words / @battles.count.to_f).round(2)
end

def words_on_round
battles_words.count / (@battles.count * ROUNDS_ON_BATTLE)
end

def delete_stopwords_from_texts
prepositions = File.read('prepositions.txt').split(',').map!(&:upcase)
battles_words.reject! { |word| prepositions.include?(word.upcase) }
end

private

def unique_bad_words
@unique_bad_words ||= RussianObscenity.find(@battles.join(' '))
end
end
23 changes: 23 additions & 0 deletions 2333/2/libs/rapper_reader.rb
@@ -0,0 +1,23 @@
require_relative 'rapper.rb'

# The class that creates a rappers array
class RappersReader
attr_reader :rappers
def initialize
@rappers = create_rappers_array
end

def create_rappers_array
new_rappers_array = []
json_of_rappers.each do |name, battles|
new_rappers_array << Rapper.new(name, battles)
end
new_rappers_array
end

private

def json_of_rappers
JSON.parse(File.read('data.json'))
end
end
18 changes: 18 additions & 0 deletions 2333/2/libs/rapper_registry.rb
@@ -0,0 +1,18 @@
# The class that search rappers in array of rappers
class RapperRegistry
def initialize(rappers)
@rappers = rappers
end

def select_rapper(name)
@rappers.select { |rapper| rapper.name == name }
end

def search_name(name)
names.include?(name)
end

def names
@rappers.map(&:name)
end
end
23 changes: 23 additions & 0 deletions 2333/2/libs/texts_parser.rb
@@ -0,0 +1,23 @@
# # Class that parse text files to hash
class TextsParser
def initialize
@hash = Hash.new([])
end

def self.name_split(file)
file.split(/(против|VS|vs)/)[0].strip
end

def self.json_file_create(hash)
File.open('data.json', 'w') { |file| file.puts hash.to_json }
end

def data_json_parse
Dir.foreach(File.join(Dir.pwd, 'rap-battles')).each do |file|
file_name = 'rap-battles/' + file
next unless file.strip =~ /^[\w[а-яА-Я]]/
@hash[TextsParser.name_split(file)] << File.read(file_name).tr!("\n", '')
end
TextsParser.json_file_create(@hash)
end
end
17 changes: 17 additions & 0 deletions 2333/2/libs/top_bad_words_analyzer.rb
@@ -0,0 +1,17 @@
# Class that analyzes rappers
class TopBadWordsAnalyzer
def initialize(rappers, take_value)
@rappers = rappers
@limit = take_value.to_i
end

def top_bad_words
sorted_rappers_by_number_of_bad_words.first(@limit)
end

private

def sorted_rappers_by_number_of_bad_words
@rappers.sort_by(&:number_of_bad_words).reverse
end
end
40 changes: 40 additions & 0 deletions 2333/2/libs/top_bad_words_printer.rb
@@ -0,0 +1,40 @@
require_relative './top_bad_words_analyzer.rb'

# Class that produces output from TopBadWordsAnalyzer
class TopBadWordsPrinter
HEADING = ['Name',
'Amount of battle',
'Amount of bad words',
'Amount of bad words on battles',
'Amount of words on round'].freeze
FIRST_COLUMN = 0

def initialize(rappers)
@rappers = rappers
end

def print_top_bad_words
table = Terminal::Table.new(rows: table_rows_of_sorted_rappers, headings: HEADING)
table.columns.each_with_index do |_value, index|
table.align_column(index, :center) if index > FIRST_COLUMN
end
puts table
end

private

def row_with_stats(rapper)
[rapper.name,
rapper.battles.count,
rapper.number_of_bad_words,
rapper.bad_words_on_battle,
rapper.words_on_round]
end

def table_rows_of_sorted_rappers
rows = @rappers.map do |rapper|
row_with_stats(rapper)
end
rows
end
end
19 changes: 19 additions & 0 deletions 2333/2/libs/top_words_analyzer.rb
@@ -0,0 +1,19 @@
require_relative './top_words_printer.rb'

# Class that analyzes rappers
class TopWordsAnalyzer
def initialize(rappers, selected_name)
@rappers = rappers
@name = selected_name
end

def top_words
texts_wo_stopwords.each_with_object(Hash.new(0)) { |word, hash| hash[word.downcase] += 1 }
end

private

def texts_wo_stopwords
@rappers.select { |rapper| rapper.name == @name }.first.delete_stopwords_from_texts
end
end
15 changes: 15 additions & 0 deletions 2333/2/libs/top_words_printer.rb
@@ -0,0 +1,15 @@
# Class that produces output from TopWordsAnalyzer
# :reek:ControlParameter
class TopWordsPrinter
def initialize(top_words, put_count)
@top_words = top_words
@put_count = put_count || 30
end

def print_top_words
@top_words.sort_by { |_word, count| count }.reverse!
@top_words.first(@put_count.to_i).each do |word, count|
puts "#{word} : #{count}"
end
end
end
1 change: 1 addition & 0 deletions 2333/2/my_dictionary.yml
@@ -0,0 +1 @@
- '[A-ё]+\*+[A-ё]+'
1 change: 1 addition & 0 deletions 2333/2/prepositions.txt
@@ -0,0 +1 @@
без,вокруг,для,до,из,от,у,благодаря,вопреки,согласно,наперекор,навстречу,про,сквозь,через,несмотря,между,над,перед,о,при,в,на,за,под,с,по,я,меня,мне,мной,мною,ты,обо,тебя,тебе,тобой,тобою,он,она,оно,они,его,него,ему,нему,его,им,ним,нём,её,неё,её,ней,ею,ней,нею,кто,что,какой,каков,чей,который,сколько,этот,эта,эти,тот,та,то,те,такой,такая,такое,такие,таков,такова,таково,таковы,сей,сия,сие,сии,все,весь,всякий,любой,каждый,сам,самый,другой,иной,никто,ничто,некого,нечего,нисколько,никакой,ничей,нечто,некий,некоторый,несколько,и,а,но,да,если,когда,так,тех,пор,это,вы,бы,как,ведь,был,твой,мой,же,нет,тут,есть,к,даже,вот,только,там,раунд,себя,чем,быть,quot,не,-,мы,здесь,где,вс,может,было,раз,чтобы,ни,ну,всех,лишь,тоже,т,против,еще,почему,потому,будет,а,со,этом,текст,будно,знаю,или,а,б,е,будто,их,после,баттл,твоя,дуня,тем,вам,пока,знаешь,хоть,сегодня,один,вас,теперь,твой,слова,ли,а,ей,снова,надо,видь,эй,уже,чтоб,одну,словно,лучше,хотел,хватит,хочешь,хочет,больше,очень,з,ваш,***,a,всё,либо,этим,давно,всего,часто,твои,просто,уж,того,раньше,ещё,жаль,щас,итак,во,потом,моего,точно,вверх,кого,наверно,всем,рядом,какой-то,рас,шо,том,из-за,ее,aka,f,мимо,себе,чё,че,срочно,походу,ж,давай,моя,настолько,всё-таки,чё-то,первой,самом,ко,ko,тому,чему,ровно,ладно,буду,неясно,мою,таких,вполне,возможные,пусть,удачно,твою,меж,что-то,этой,сразу,можно,
18 changes: 18 additions & 0 deletions 2333/2/versus.rb
@@ -0,0 +1,18 @@
Dir.glob('./{libs}/*.rb').each { |file| require file }
require 'bundler'
Bundler.require

parameters = ParametersParser.parse
rappers_reader = RappersReader.new
rapper_registry = RapperRegistry.new(rappers_reader.rappers)

if parameters[:top_bad_words]
analyzer = TopBadWordsAnalyzer.new(rappers_reader.rappers, parameters[:top_bad_words])
TopBadWordsPrinter.new(analyzer.top_bad_words).print_top_bad_words
elsif parameters[:name] && rapper_registry.search_name(parameters[:name])
analyzer = TopWordsAnalyzer.new(rappers_reader.rappers, parameters[:name])
TopWordsPrinter.new(analyzer.top_words, parameters[:top_words]).print_top_words
else
puts "Рэпер #{parameters[:name]} не известен мне. Зато мне известны:"
rapper_registry.names.each { |item| puts item }
end

0 comments on commit 934ca6e

Please sign in to comment.