Skip to content
This repository was archived by the owner on Dec 1, 2022. It is now read-only.

Commit f239379

Browse files
committed
add_demo_restaurant_bot
1 parent 08cdcb9 commit f239379

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+399
-3
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
Metadata-Version: 1.0
2+
Name: python_programming_demo_app
3+
Version: 0.0.1
4+
Summary: UNKNOWN
5+
Home-page: http://sakaijunsoccer.appspot.com
6+
Author: jsakai
7+
Author-email: [email protected]
8+
License: MIT
9+
Description-Content-Type: UNKNOWN
10+
Description: Roboter
11+
====
12+
13+
## Install
14+
15+
1. 以下のようにパーケージをインストールするか、もしくはroboterフォルダーを実行するディレクトリへ置いてください。
16+
$ python setup.py develop
17+
18+
or
19+
20+
$ ls
21+
roboter
22+
23+
24+
## Requirement
25+
pip install termcolor==1.1.0
26+
27+
28+
## Usage
29+
30+
1. 以下のようにtalk_about_restaurant関数を呼び出すと実行可能です。
31+
32+
# vim main.py
33+
import roboter.controller.conversation
34+
roboter.controller.conversation.talk_about_restaurant()
35+
36+
2. 実行して下さい。
37+
$ python main.py
38+
39+
(オプション: 保存するCSVやテンプレート先を変更する場合は、settings.pyに以下の値を入れる。)
40+
# vim settings.py
41+
CSV_FILE_PATH = '/tmp/test.csv'
42+
TEMPLATE_PATH = '/tmp/templates/'
43+
44+
# settings.pyファイルを作成した場合は、変更しない場合のDefaultは以下に設定する
45+
CSV_FILE_PATH = None
46+
TEMPLATE_PATH = None
47+
48+
49+
Platform: UNKNOWN
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
Roboter
2+
====
3+
4+
## Install
5+
6+
1. 이하 패키지를 인스톨하거나, 실행하실 디렉토리에 roboter 폴더를 옮겨주시기 바랍니다.
7+
$ python setup.py develop
8+
9+
or
10+
11+
$ ls
12+
roboter
13+
14+
15+
## Requirement
16+
pip install termcolor==1.1.0
17+
18+
19+
## Usage
20+
21+
1. 이하와 같이 talk_about_restaurant 함수를 불러오면 실행할 수 있습니다.
22+
23+
# vim main.py
24+
import roboter.controller.conversation
25+
roboter.controller.conversation.talk_about_restaurant()
26+
27+
2. 실행해주세요
28+
$ python main.py
29+
30+
(옵션: 보존할 csv 나 템플릿을 변경할 경우는 settings.py 에 아래를 추가합니다)
31+
32+
# vim settings.py
33+
CSV_FILE_PATH = '/tmp/test.csv'
34+
TEMPLATE_PATH = '/tmp/templates/'
35+
36+
# settings.py 파일을 작성한 경우에는, 변경하지 않은 경우의 default 는 다음과 같이 설정합니다.
37+
CSV_FILE_PATH = None
38+
TEMPLATE_PATH = None
39+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import roboter.controller.conversation
2+
roboter.controller.conversation.talk_about_restaurant()

application/python_programming_demo_app-0.0.1/python_programming_demo_app-0.0.1/roboter/__init__.py

Whitespace-only changes.

application/python_programming_demo_app-0.0.1/python_programming_demo_app-0.0.1/roboter/controller/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"""Controller for speaking with robot"""
2+
from roboter.models import robot
3+
4+
5+
def talk_about_restaurant():
6+
"""Function to speak with robot"""
7+
restaurant_robot = robot.RestaurantRobot()
8+
restaurant_robot.hello()
9+
restaurant_robot.recommend_restaurant()
10+
restaurant_robot.ask_user_favorite()
11+
restaurant_robot.thank_you()
12+

application/python_programming_demo_app-0.0.1/python_programming_demo_app-0.0.1/roboter/models/__init__.py

Whitespace-only changes.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
"""Generates ranking model to write to CSV
2+
3+
TODO (jsakai) Rewrite to DB instead of CSV
4+
"""
5+
import collections
6+
import csv
7+
import os
8+
import pathlib
9+
10+
11+
RANKING_COLUMN_NAME = 'NAME'
12+
RANKING_COLUMN_COUNT = 'COUNT'
13+
RANKING_CSV_FILE_PATH = 'ranking.csv'
14+
15+
16+
class CsvModel(object):
17+
"""Base csv model."""
18+
def __init__(self, csv_file):
19+
self.csv_file = csv_file
20+
if not os.path.exists(csv_file):
21+
pathlib.Path(csv_file).touch()
22+
23+
24+
class RankingModel(CsvModel):
25+
"""Definition of class that generates ranking model to write to CSV"""
26+
def __init__(self, csv_file=None, *args, **kwargs):
27+
if not csv_file:
28+
csv_file = self.get_csv_file_path()
29+
super().__init__(csv_file, *args, **kwargs)
30+
self.column = [RANKING_COLUMN_NAME, RANKING_COLUMN_COUNT]
31+
self.data = collections.defaultdict(int)
32+
self.load_data()
33+
34+
def get_csv_file_path(self):
35+
"""Set csv file path.
36+
37+
Use csv path if set in settings, otherwise use default
38+
"""
39+
csv_file_path = None
40+
try:
41+
import settings
42+
if settings.CSV_FILE_PATH:
43+
csv_file_path = settings.CSV_FILE_PATH
44+
except ImportError:
45+
pass
46+
47+
if not csv_file_path:
48+
csv_file_path = RANKING_CSV_FILE_PATH
49+
return csv_file_path
50+
51+
def load_data(self):
52+
"""Load csv data.
53+
54+
Returns:
55+
dict: Returns ranking data of dict type.
56+
"""
57+
with open(self.csv_file, 'r+') as csv_file:
58+
reader = csv.DictReader(csv_file)
59+
for row in reader:
60+
self.data[row[RANKING_COLUMN_NAME]] = int(
61+
row[RANKING_COLUMN_COUNT])
62+
return self.data
63+
64+
def save(self):
65+
"""Save data to csv file."""
66+
# TODO (jsakai) Use locking mechanism for avoiding dead lock issue
67+
with open(self.csv_file, 'w+') as csv_file:
68+
writer = csv.DictWriter(csv_file, fieldnames=self.column)
69+
writer.writeheader()
70+
71+
for name, count in self.data.items():
72+
writer.writerow({
73+
RANKING_COLUMN_NAME: name,
74+
RANKING_COLUMN_COUNT: count
75+
})
76+
77+
def get_most_popular(self, not_list=None):
78+
"""Fetch the data of the top most ranking.
79+
80+
Args:
81+
not_list (list): Excludes the name on the list.
82+
83+
Returns:
84+
str: Returns the data of the top most ranking
85+
"""
86+
if not_list is None:
87+
not_list = []
88+
89+
if not self.data:
90+
return None
91+
92+
sorted_data = sorted(self.data, key=self.data.get, reverse=True)
93+
for name in sorted_data:
94+
if name in not_list:
95+
continue
96+
return name
97+
98+
def increment(self, name):
99+
"""Increase rank for the give name."""
100+
self.data[name.title()] += 1
101+
self.save()
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
"""Defined a robot model """
2+
from roboter.models import ranking
3+
from roboter.views import console
4+
5+
6+
DEFAULT_ROBOT_NAME = 'Roboko'
7+
8+
9+
class Robot(object):
10+
"""Base model for Robot."""
11+
12+
def __init__(self, name=DEFAULT_ROBOT_NAME, user_name='',
13+
speak_color='green'):
14+
self.name = name
15+
self.user_name = user_name
16+
self.speak_color = speak_color
17+
18+
def hello(self):
19+
"""Returns words to the user that the robot speaks at the beginning."""
20+
while True:
21+
template = console.get_template('hello.txt', self.speak_color)
22+
user_name = input(template.substitute({
23+
'robot_name': self.name}))
24+
25+
if user_name:
26+
self.user_name = user_name.title()
27+
break
28+
29+
30+
class RestaurantRobot(Robot):
31+
"""Handle data model on restaurant."""
32+
33+
def __init__(self, name=DEFAULT_ROBOT_NAME):
34+
super().__init__(name=name)
35+
self.ranking_model = ranking.RankingModel()
36+
37+
def _hello_decorator(func):
38+
"""Decorator to say a greeting if you are not greeting the user."""
39+
def wrapper(self):
40+
if not self.user_name:
41+
self.hello()
42+
return func(self)
43+
return wrapper
44+
45+
@_hello_decorator
46+
def recommend_restaurant(self):
47+
"""Show restaurant recommended restaurant to the user."""
48+
new_recommend_restaurant = self.ranking_model.get_most_popular()
49+
if not new_recommend_restaurant:
50+
return None
51+
52+
will_recommend_restaurants = [new_recommend_restaurant]
53+
while True:
54+
template = console.get_template('greeting.txt', self.speak_color)
55+
is_yes = input(template.substitute({
56+
'robot_name': self.name,
57+
'user_name': self.user_name,
58+
'restaurant': new_recommend_restaurant
59+
}))
60+
61+
if is_yes.lower() == 'y' or is_yes.lower() == 'yes':
62+
break
63+
64+
if is_yes.lower() == 'n' or is_yes.lower() == 'no':
65+
new_recommend_restaurant = self.ranking_model.get_most_popular(
66+
not_list=will_recommend_restaurants)
67+
if not new_recommend_restaurant:
68+
break
69+
will_recommend_restaurants.append(new_recommend_restaurant)
70+
71+
@_hello_decorator
72+
def ask_user_favorite(self):
73+
"""Collect favorite restaurant information from users."""
74+
while True:
75+
template = console.get_template(
76+
'which_restaurant.txt', self.speak_color)
77+
restaurant = input(template.substitute({
78+
'robot_name': self.name,
79+
'user_name': self.user_name,
80+
}))
81+
if restaurant:
82+
self.ranking_model.increment(restaurant)
83+
break
84+
85+
@_hello_decorator
86+
def thank_you(self):
87+
"""Show words of appreciation to users."""
88+
template = console.get_template('good_by.txt', self.speak_color)
89+
print(template.substitute({
90+
'robot_name': self.name,
91+
'user_name': self.user_name,
92+
}))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
$robot_name: $user_name 씨 감사합니다.
2+
$robot_name: Thank you so much, $user_name! 좋은 하루 되세요. 안녕히가세요
3+
Have a good day!
4+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
제가 추천하는 레스토랑은 $restaurant 입니다.
2+
I recommend $restaurant restaurant. 이 레스토랑을 좋아하십니까? [Yes/No]
3+
Do you like it? [y/n]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
안녕하세요 저는 $robot_name 입니다. 당신의 이름은 무엇입니까?
2+
Hello, I am $robot_name. What is your name?
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
$user_name 씨, 좋아하는 레스토랑은 어디인가요?
2+
$user_name, which restaurants do you like?

application/python_programming_demo_app-0.0.1/python_programming_demo_app-0.0.1/roboter/views/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""Utils to display to be returned to the user on the console."""
2+
import os
3+
import string
4+
5+
import termcolor
6+
7+
8+
def get_template_dir_path():
9+
"""Return the path of the template's directory.
10+
11+
Returns:
12+
str: The template dir path.
13+
"""
14+
template_dir_path = None
15+
try:
16+
import settings
17+
if settings.TEMPLATE_PATH:
18+
template_dir_path = settings.TEMPLATE_PATH
19+
except ImportError:
20+
pass
21+
22+
if not template_dir_path:
23+
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
24+
template_dir_path = os.path.join(base_dir, 'templates')
25+
26+
return template_dir_path
27+
28+
29+
class NoTemplateError(Exception):
30+
"""No Template Error"""
31+
32+
33+
def find_template(temp_file):
34+
"""Find for template file in the given location.
35+
36+
Returns:
37+
str: The template file path
38+
39+
Raises:
40+
NoTemplateError: If the file does not exists.
41+
"""
42+
template_dir_path = get_template_dir_path()
43+
temp_file_path = os.path.join(template_dir_path, temp_file)
44+
if not os.path.exists(temp_file_path):
45+
raise NoTemplateError('Could not find {}'.format(temp_file))
46+
return temp_file_path
47+
48+
49+
def get_template(template_file_path, color=None):
50+
"""Return the path of the template.
51+
52+
Args:
53+
template_file_path (str): The template file path
54+
color: (str): Color formatting for output in terminal
55+
See in more details: https://pypi.python.org/pypi/termcolor
56+
57+
Returns:
58+
string.Template: Return templates with characters in templates.
59+
"""
60+
template = find_template(template_file_path)
61+
with open(template, 'r', encoding='utf-8') as template_file:
62+
contents = template_file.read()
63+
contents = contents.rstrip(os.linesep)
64+
contents = '{splitter}{sep}{contents}{sep}{splitter}{sep}'.format(
65+
contents=contents, splitter="=" * 60, sep=os.linesep)
66+
contents = termcolor.colored(contents, color)
67+
return string.Template(contents)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[egg_info]
2+
tag_build =
3+
tag_date = 0
4+

0 commit comments

Comments
 (0)