Решение на Четвърта задача от Мирослав Крамолински

Обратно към всички решения

Към профила на Мирослав Крамолински

Резултати

  • 4 точки от тестове
  • 0 бонус точки
  • 4 точки общо
  • 28 успешни тест(а)
  • 13 неуспешни тест(а)

Код

class Validations
def Validations.email?(data)
email = /\A[[:alnum:]](\w|\+|\.|\-){,200}@/.match(data)
email != nil && hostname?(email.post_match)
end
def Validations.phone?(data)
num = /\A(\+\d{1,3}|00[1-9]\d{,2}|0)([ \-\(\)]{,2}\d){6,11}\z/.match(data)
num != nil
end
def Validations.hostname?(data)
host = /\A(\p{Alnum}((\p{Alnum}|\-){,61}\p{Alnum})?\.)+[[:alpha:]]{2,3}(\.[[:alpha:]]{2})?\z/.match(data)
host != nil && data.include?("-.") == false
end
def Validations.ip_address?(data)
ip = /\A([1-9]\d{0,2})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\z/.match(data)
return false if ip == nil || ip[1] == nil || ip[2] == nil || ip[3] == nil || ip[4] == nil
ip[1].to_i <= 255 && ip[2].to_i <= 255 && ip[3].to_i <= 255 && ip[4].to_i <= 255
end
def Validations.number?(data)
number = /\A-?(0|[1-9]\d*)(\.\d+|\d*)\z/.match(data)
number != nil
end
def Validations.integer?(data)
integer = /\A-?(0|[1-9]\d*)\z/.match(data)
integer != nil
end
def Validations.date?(data)
date = /\A(\d{4})\-(\d{2})\-(\d{2})\z/.match(data)
date != nil && date[2].to_i <= 12 && date[3].to_i <= 31
end
def Validations.time?(data)
time = /\A(\d{2}):(\d{2}):(\d{2})\z/.match(data)
time != nil && time[1].to_i <= 23 && time[2].to_i <= 59 && time[3].to_i <= 59
end
def Validations.date_time?(data)
time = /\A(\d{4})\-(\d{2})\-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})\z/.match(data)
date = time != nil && time[2].to_i <= 12 && time[3].to_i <= 31
date && time[4].to_i <= 23 && time[5].to_i <= 59 && time[6].to_i <= 59
end
end
class PrivacyFilter
attr_writer :preserve_phone_country_code, :preserve_email_hostname, :partially_preserve_email_username
def initialize(text)
@data, @email, @phone, @filter = text, '[EMAIL]', '[PHONE]', '[FILTERED]'
@preserve_phone_country_code, @preserve_email_hostname, @partially_preserve_email_username = false, false, false
self
end
def filter_email
@data.gsub!(/\p{Alnum}(\w|\+|\.|\-){,200}@(\p{Alnum}((\p{Alnum}|\-){,61}\p{Alnum})?\.)+\p{Alnum}{2,3}/) do |match|
email(match)
end
end
def filter_phone
@data.gsub!(/(\+\d{1,3}|00[1-9]\d{,2}|0)([ \-\(\)]{,2}\d){6,11}/) { |match| phone(match, $1.to_s) }
end
def phone(phone_number, code)
return phone_with_preserved_country_code(phone_number, code) if phone_number[0] == '+' or phone_number[1] == '0'
@phone
end
def phone_with_preserved_country_code(number, country_code)
return country_code + ' ' + @filter if @preserve_phone_country_code == true
number
end
def email(match)
return @email if @partially_preserve_email_username == false and @preserve_email_hostname == false
return match.gsub(/.*@/, @filter + '@' + $'.to_s) if @partially_preserve_email_username == false
partially_preserved_username(match)
end
def partially_preserved_username(email_address)
match = /.*@/.match(email_address)
return @filter + '@' + match.post_match.to_s if $~.to_s.length < 6
$~.to_s[0] + $~.to_s[1] + $~.to_s[2] + @filter + '@' + match.post_match.to_s
end
def filtered
filter_email
filter_phone
@data
end
end

Лог от изпълнението

..F....FFFFFFF.....F...F..F.......F....F.

Failures:

  1) PrivacyFilter obfuscates more complicated emails
     Failure/Error: PrivacyFilter.new(text).filtered
     RuntimeError:
       can't modify frozen String
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `gsub!'
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `filter_email'
     # /tmp/d20130203-23049-n8mhx/solution.rb:92:in `filtered'
     # /tmp/d20130203-23049-n8mhx/spec.rb:5:in `filter'
     # /tmp/d20130203-23049-n8mhx/spec.rb:40:in `block (3 levels) in <top (required)>'
     # /tmp/d20130203-23049-n8mhx/spec.rb:39:in `each'
     # /tmp/d20130203-23049-n8mhx/spec.rb:39:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) PrivacyFilter does not brake with unicode
     Failure/Error: filter.filtered
     Encoding::CompatibilityError:
       incompatible encoding regexp match (ASCII-8BIT regexp with UTF-8 string)
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `gsub!'
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `filter_email'
     # /tmp/d20130203-23049-n8mhx/solution.rb:92:in `filtered'
     # /tmp/d20130203-23049-n8mhx/spec.rb:17:in `partially_filter_email_usernames'
     # /tmp/d20130203-23049-n8mhx/spec.rb:73:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) PrivacyFilter filters more complex phone numbers
     Failure/Error: PrivacyFilter.new(text).filtered
     RuntimeError:
       can't modify frozen String
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `gsub!'
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `filter_email'
     # /tmp/d20130203-23049-n8mhx/solution.rb:92:in `filtered'
     # /tmp/d20130203-23049-n8mhx/spec.rb:5:in `filter'
     # /tmp/d20130203-23049-n8mhx/spec.rb:85:in `block (3 levels) in <top (required)>'
     # /tmp/d20130203-23049-n8mhx/spec.rb:84:in `each'
     # /tmp/d20130203-23049-n8mhx/spec.rb:84:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) PrivacyFilter does not filter invalid phone numbers
     Failure/Error: PrivacyFilter.new(text).filtered
     RuntimeError:
       can't modify frozen String
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `gsub!'
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `filter_email'
     # /tmp/d20130203-23049-n8mhx/solution.rb:92:in `filtered'
     # /tmp/d20130203-23049-n8mhx/spec.rb:5:in `filter'
     # /tmp/d20130203-23049-n8mhx/spec.rb:96:in `block (3 levels) in <top (required)>'
     # /tmp/d20130203-23049-n8mhx/spec.rb:95:in `each'
     # /tmp/d20130203-23049-n8mhx/spec.rb:95:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) PrivacyFilter preserves whitespace around phones
     Failure/Error: filter(' +359881212-12-1 2 or...').should eq ' [PHONE] or...'
       
       expected: " [PHONE] or..."
            got: " +359881212-12-1 2 or..."
       
       (compared using ==)
     # /tmp/d20130203-23049-n8mhx/spec.rb:101:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) PrivacyFilter filters more than one phone or email
     Failure/Error: filter(text).should eq filtered
       
       expected: "\n      Contacts\n\n      Phones: [PHONE] or [PHONE]\n      Email: [EMAIL] or [EMAIL]\n    "
            got: "\n      Contacts\n\n      Phones: +1 (555) 123-456-99 or 004412125543\n      Email: [EMAIL] or [EMAIL]\n    "
       
       (compared using ==)
       
       Diff:
       @@ -1,7 +1,7 @@
        
              Contacts
        
       -      Phones: [PHONE] or [PHONE]
       +      Phones: +1 (555) 123-456-99 or 004412125543
              Email: [EMAIL] or [EMAIL]
            
     # /tmp/d20130203-23049-n8mhx/spec.rb:119:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) PrivacyFilter allows country code to be preserved for internationally-formatted phone numbers
     Failure/Error: filter.filtered.should eq filtered
     RuntimeError:
       can't modify frozen String
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `gsub!'
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `filter_email'
     # /tmp/d20130203-23049-n8mhx/solution.rb:92:in `filtered'
     # /tmp/d20130203-23049-n8mhx/spec.rb:132:in `block (3 levels) in <top (required)>'
     # /tmp/d20130203-23049-n8mhx/spec.rb:129:in `each'
     # /tmp/d20130203-23049-n8mhx/spec.rb:129:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  8) PrivacyFilter separates preserved country code from filtered phone with a space
     Failure/Error: filter.filtered.should eq filtered
     RuntimeError:
       can't modify frozen String
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `gsub!'
     # /tmp/d20130203-23049-n8mhx/solution.rb:60:in `filter_email'
     # /tmp/d20130203-23049-n8mhx/solution.rb:92:in `filtered'
     # /tmp/d20130203-23049-n8mhx/spec.rb:144:in `block (3 levels) in <top (required)>'
     # /tmp/d20130203-23049-n8mhx/spec.rb:141:in `each'
     # /tmp/d20130203-23049-n8mhx/spec.rb:141:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  9) Validations can validate more complex phone numbers
     Failure/Error: Validations.phone?(phone).should be(valid)
       
       expected #<FalseClass:0> => false
            got #<TrueClass:2> => true
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       'actual.should eq(expected)' if you don't care about
       object identity in this example.
     # /tmp/d20130203-23049-n8mhx/spec.rb:210:in `block (3 levels) in <top (required)>'
     # /tmp/d20130203-23049-n8mhx/spec.rb:209:in `each'
     # /tmp/d20130203-23049-n8mhx/spec.rb:209:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  10) Validations validates IP addresses
     Failure/Error: Validations.ip_address?('0.0.0.0').should be_true
       expected: true value
            got: false
     # /tmp/d20130203-23049-n8mhx/spec.rb:240:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  11) Validations validates more complex numbers
     Failure/Error: Validations.number?('00').should be_false
       expected: false value
            got: true
     # /tmp/d20130203-23049-n8mhx/spec.rb:263:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  12) Validations does not allow zero months or days in dates
     Failure/Error: Validations.date?('1000-00-01').should be_false
       expected: false value
            got: true
     # /tmp/d20130203-23049-n8mhx/spec.rb:315:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  13) Validations validates datetime values
     Failure/Error: Validations.date_time?('2012-00-19T23:59:00').should be_false
       expected: false value
            got: true
     # /tmp/d20130203-23049-n8mhx/spec.rb:352:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.04926 seconds
41 examples, 13 failures

Failed examples:

rspec /tmp/d20130203-23049-n8mhx/spec.rb:30 # PrivacyFilter obfuscates more complicated emails
rspec /tmp/d20130203-23049-n8mhx/spec.rb:72 # PrivacyFilter does not brake with unicode
rspec /tmp/d20130203-23049-n8mhx/spec.rb:76 # PrivacyFilter filters more complex phone numbers
rspec /tmp/d20130203-23049-n8mhx/spec.rb:89 # PrivacyFilter does not filter invalid phone numbers
rspec /tmp/d20130203-23049-n8mhx/spec.rb:100 # PrivacyFilter preserves whitespace around phones
rspec /tmp/d20130203-23049-n8mhx/spec.rb:104 # PrivacyFilter filters more than one phone or email
rspec /tmp/d20130203-23049-n8mhx/spec.rb:122 # PrivacyFilter allows country code to be preserved for internationally-formatted phone numbers
rspec /tmp/d20130203-23049-n8mhx/spec.rb:136 # PrivacyFilter separates preserved country code from filtered phone with a space
rspec /tmp/d20130203-23049-n8mhx/spec.rb:184 # Validations can validate more complex phone numbers
rspec /tmp/d20130203-23049-n8mhx/spec.rb:237 # Validations validates IP addresses
rspec /tmp/d20130203-23049-n8mhx/spec.rb:257 # Validations validates more complex numbers
rspec /tmp/d20130203-23049-n8mhx/spec.rb:314 # Validations does not allow zero months or days in dates
rspec /tmp/d20130203-23049-n8mhx/spec.rb:347 # Validations validates datetime values

История (1 версия и 0 коментара)

Мирослав обнови решението на 28.11.2012 14:55 (преди почти 12 години)

+class Validations
+ def Validations.email?(data)
+ email = /\A[[:alnum:]](\w|\+|\.|\-){,200}@/.match(data)
+ email != nil && hostname?(email.post_match)
+ end
+
+ def Validations.phone?(data)
+ num = /\A(\+\d{1,3}|00[1-9]\d{,2}|0)([ \-\(\)]{,2}\d){6,11}\z/.match(data)
+ num != nil
+ end
+
+ def Validations.hostname?(data)
+ host = /\A(\p{Alnum}((\p{Alnum}|\-){,61}\p{Alnum})?\.)+[[:alpha:]]{2,3}(\.[[:alpha:]]{2})?\z/.match(data)
+ host != nil && data.include?("-.") == false
+ end
+
+ def Validations.ip_address?(data)
+ ip = /\A([1-9]\d{0,2})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\z/.match(data)
+ return false if ip == nil || ip[1] == nil || ip[2] == nil || ip[3] == nil || ip[4] == nil
+ ip[1].to_i <= 255 && ip[2].to_i <= 255 && ip[3].to_i <= 255 && ip[4].to_i <= 255
+ end
+
+ def Validations.number?(data)
+ number = /\A-?(0|[1-9]\d*)(\.\d+|\d*)\z/.match(data)
+ number != nil
+ end
+
+ def Validations.integer?(data)
+ integer = /\A-?(0|[1-9]\d*)\z/.match(data)
+ integer != nil
+ end
+
+ def Validations.date?(data)
+ date = /\A(\d{4})\-(\d{2})\-(\d{2})\z/.match(data)
+ date != nil && date[2].to_i <= 12 && date[3].to_i <= 31
+ end
+
+ def Validations.time?(data)
+ time = /\A(\d{2}):(\d{2}):(\d{2})\z/.match(data)
+ time != nil && time[1].to_i <= 23 && time[2].to_i <= 59 && time[3].to_i <= 59
+ end
+
+ def Validations.date_time?(data)
+ time = /\A(\d{4})\-(\d{2})\-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})\z/.match(data)
+ date = time != nil && time[2].to_i <= 12 && time[3].to_i <= 31
+ date && time[4].to_i <= 23 && time[5].to_i <= 59 && time[6].to_i <= 59
+ end
+end
+
+class PrivacyFilter
+ attr_writer :preserve_phone_country_code, :preserve_email_hostname, :partially_preserve_email_username
+
+ def initialize(text)
+ @data, @email, @phone, @filter = text, '[EMAIL]', '[PHONE]', '[FILTERED]'
+ @preserve_phone_country_code, @preserve_email_hostname, @partially_preserve_email_username = false, false, false
+ self
+ end
+
+ def filter_email
+ @data.gsub!(/\p{Alnum}(\w|\+|\.|\-){,200}@(\p{Alnum}((\p{Alnum}|\-){,61}\p{Alnum})?\.)+\p{Alnum}{2,3}/) do |match|
+ email(match)
+ end
+ end
+
+ def filter_phone
+ @data.gsub!(/(\+\d{1,3}|00[1-9]\d{,2}|0)([ \-\(\)]{,2}\d){6,11}/) { |match| phone(match, $1.to_s) }
+ end
+
+ def phone(phone_number, code)
+ return phone_with_preserved_country_code(phone_number, code) if phone_number[0] == '+' or phone_number[1] == '0'
+ @phone
+ end
+
+ def phone_with_preserved_country_code(number, country_code)
+ return country_code + ' ' + @filter if @preserve_phone_country_code == true
+ number
+ end
+
+ def email(match)
+ return @email if @partially_preserve_email_username == false and @preserve_email_hostname == false
+ return match.gsub(/.*@/, @filter + '@' + $'.to_s) if @partially_preserve_email_username == false
+ partially_preserved_username(match)
+ end
+
+ def partially_preserved_username(email_address)
+ match = /.*@/.match(email_address)
+ return @filter + '@' + match.post_match.to_s if $~.to_s.length < 6
+ $~.to_s[0] + $~.to_s[1] + $~.to_s[2] + @filter + '@' + match.post_match.to_s
+ end
+
+ def filtered
+ filter_email
+ filter_phone
+ @data
+ end
+end