serendipitous 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3fbb7d75ff3884429bbb8f5950a783c8ae1fa1c6
4
+ data.tar.gz: 10d6ab78198c81212a8d3b5cc5c955b4d359b37c
5
+ SHA512:
6
+ metadata.gz: 85cb1fd1e3278b58f7227cb0a01e52f0d3f53247d04f74272147eeda62b7bf8409af0f9515acc4476ce8b00493d9b5134abd7657fb49fb30693fa926804aec7d
7
+ data.tar.gz: d0cce11fa0d840528c2198bcec0e32d6d5487c25ffa68f3bcb274ae9669029926326717c93ffacb6b8a0602736f3bd7d4bbe0bb584f72870080c85676c9e2aff
@@ -0,0 +1,20 @@
1
+ # Temp Content class stand-in for notebook gem
2
+ class Content
3
+ attr_reader :data
4
+
5
+ def initialize fields={}
6
+ defaults = {
7
+ type: 'Character',
8
+ title: '',
9
+ description: ''
10
+ }
11
+ @data = defaults.merge(fields)
12
+ end
13
+
14
+ # TODO: find jesus
15
+ def method_missing method
16
+ # TODO: Does this let you data[method][some_list][some_value]
17
+ data[method]
18
+ end
19
+
20
+ end
@@ -0,0 +1,26 @@
1
+ # A layer of higher level methods on top of Content
2
+ class ContentService
3
+ def self.unanswered_fields(content)
4
+ content.data.select do |key, value|
5
+ next if blacklisted_fields.include? key
6
+ #next unless whitelisted_fields.include? key
7
+
8
+ unanswered?(value)
9
+ end
10
+ end
11
+
12
+ def self.unanswered?(field)
13
+ # TODO: Compare against defaults
14
+ field.length == 0
15
+ end
16
+
17
+ # TODO: make this smarter
18
+ def self.whitelisted_fields
19
+ @whitelisted_fields ||= %w(title description some_blank_field)
20
+ end
21
+
22
+ # TODO: make this smarter
23
+ def self.blacklisted_fields
24
+ @blacklisted_fields ||= %w(id user_id)
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ # TODO: scope this class (and all other classes) into Serendipity:: namespace
2
+ # TODO: mix multiple pieces of content
3
+ # TODO: specify parameters such as genre, reading level, etc
4
+
5
+ # Looks at a piece of content and provides a writing prompt about it
6
+ class PromptService
7
+ def self.prompt(content)
8
+ "What is #{content}?"
9
+ end
10
+ end
@@ -0,0 +1,71 @@
1
+ # TODO: scope this class (and all other classes) into Serendipity:: namespace
2
+ # Takes a look at a Content and asks a question about it
3
+ class QuestionService
4
+ def self.question(content)
5
+ # TODO: Make "What is" a token based on content type + field
6
+ # e.g. location-reference --> "Where is _____?""
7
+ field_to_answer = answerable_fields_for(content).keys.sample
8
+ puts "Answerable_fields: #{answerable_fields_for(content).keys}"
9
+ build_question content, field_to_answer
10
+ end
11
+
12
+ def self.answerable_fields_for(content)
13
+ # TODO: aggregate QuestionServiceLayer responses here
14
+ ContentService.unanswered_fields(content)
15
+ end
16
+
17
+ def self.build_question content, field
18
+ type = field_type(field)
19
+ template = questions_for(type).sample
20
+ .gsub('<<field>>', field.to_s.gsub('_', ' '))
21
+ # TODO: SanitizationService for things like ^
22
+
23
+ TemplateService.perform_data_replacements(template, content)
24
+ end
25
+
26
+ def self.field_type value
27
+ # TODO: piggyback on Watson NLC
28
+ puts "Looking at [#{value.inspect}]"
29
+ case value
30
+ when :best_friend, :mother
31
+ 'Character'
32
+ else
33
+ 'Data'
34
+ end
35
+ end
36
+
37
+ # TODO: stick this in internationalized yaml
38
+ # TODO: make this smarter
39
+ def self.questions_for type
40
+ case type
41
+ when 'Character'
42
+ [
43
+ # e.g. field=best_friend -> "Who is Alice's best friend?"
44
+ "Who is [[title]]'s <<field>>?"
45
+ ]
46
+ when 'Location'
47
+ [
48
+ # e.g. field=hometown -> "Where is Alice's home town?"
49
+ "Where is [[title]]'s <<field>>?"
50
+ ]
51
+ when 'Item'
52
+ [
53
+ # e.g. field=favorite_item -> "What is Alice's favorite item?"
54
+ "What is [[title]]'s <<field>>?"
55
+ ]
56
+ when 'Data'
57
+ [
58
+ # e.g. field=height -> "What is Alice's height?"
59
+ # TODO: special cases here:
60
+ # height -> "How tall is..."
61
+ # weight -> "How much does...weigh?"
62
+ # age -> "How old is..."
63
+ "What is [[title]]'s <<field>>?"
64
+ ]
65
+ else
66
+ [
67
+ 'Dunno lol'
68
+ ]
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,10 @@
1
+ # TODO: scope this class (and all other classes) into Serendipity:: namespace
2
+ # TODO: ExternalDataLayer to base suggestions on real-world stats provided
3
+ # elsewhere
4
+
5
+ # Looks at a piece of content and makes a suggestion on improving it
6
+ class SuggestionService
7
+ def self.suggestion(content)
8
+ "What is #{content}?"
9
+ end
10
+ end
@@ -0,0 +1,39 @@
1
+ # Template service
2
+ class TemplateService
3
+ # Regex to determine whether a word is in template replacement format
4
+ # e.g. [[user.name]] or [[day_of_week]]
5
+ TOKEN_REGEX = /\[\[([^\]]+)\]\]/
6
+ # TODO: Support nested template replacement [[e.g. another_user.title]] instead of [[title]]
7
+
8
+ # Regex to find symbolic reductions
9
+ SRAI_REGEX = /<<([^>]+)>>/
10
+ # TODO: implement symbolic reductions
11
+
12
+ def self.perform_data_replacements template, content
13
+ template.gsub(TOKEN_REGEX) do |token|
14
+ replacement_for(remove_brackets(token), content)
15
+ end
16
+ end
17
+
18
+ def self.perform_symbolic_reductions template
19
+ # template.gsub(SRAI_REGEX) do |srai|
20
+ # reduction_template = KeywordMatcherService.match_to_template srai
21
+ # replaced_template = TemplateReplacerService.replace_replacements reduction_template
22
+
23
+ # replaced_template
24
+ # end
25
+ end
26
+
27
+ def self.replacement_for token, content
28
+ # TODO: not this
29
+ content.send token
30
+ end
31
+
32
+ private
33
+
34
+ def self.remove_brackets(token)
35
+ token.sub(/^\[\[/, '')
36
+ .sub(/\]\]$/, '')
37
+ end
38
+
39
+ end
@@ -0,0 +1,24 @@
1
+ require 'serendipitous/content'
2
+
3
+ require 'serendipitous/question_service'
4
+ require 'serendipitous/suggestion_service'
5
+ require 'serendipitous/prompt_service'
6
+ require 'serendipitous/content_service'
7
+ require 'serendipitous/template_service'
8
+
9
+ # Gem interface
10
+ class Serendipitous
11
+ def self.question(content)
12
+ QuestionService.question(content)
13
+ end
14
+
15
+ def self.suggestion(_content)
16
+ end
17
+
18
+ def self.prompt(_content)
19
+ end
20
+
21
+ # maybe
22
+ # def self.problems content
23
+ # end
24
+ end
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: serendipitous
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Brown
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-20 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: An engine for creative feedback
14
+ email: andrew@indentlabs.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/serendipitous.rb
20
+ - lib/serendipitous/content.rb
21
+ - lib/serendipitous/content_service.rb
22
+ - lib/serendipitous/prompt_service.rb
23
+ - lib/serendipitous/question_service.rb
24
+ - lib/serendipitous/suggestion_service.rb
25
+ - lib/serendipitous/template_service.rb
26
+ homepage: http://indentlabs.com/serendipitous
27
+ licenses:
28
+ - MIT
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 2.4.5.1
47
+ signing_key:
48
+ specification_version: 4
49
+ summary: Creative query engine
50
+ test_files: []