TOEIC730で足切りについて一言

CATEGORIES eラーニング, 英語学習by.a.takeuchi31 Comments2011.01.24

武田薬品が新卒の採用条件にTOEIC730の取得を義務付けたそうです。

ネット上では賛否両論上がっているようですが、採用基準に語学能力を含めることは全く問題ないと思います。論文読むにしても、薬剤系のマニュアル読むにしても、TOEIC730点は最低限必要だと思います。今後の海外展開を考えると、社員全体の語学水準を上げておくことも必要でしょう。中堅以上の大学であれば、大学入学時にTOEICで500点程度の実力はあるはずです。大学4年間、就職活動までなら3年ほど。その間に、1000時間程度、つまり、1日1時間程度英語を勉強していれば730点ぐらいはとれるはずです。化学専攻で実験が忙しいとしても、これぐらいはなんとかなるはずです。

あ、前置きが長くなりましたが、言いたいのは1つだけです。
「既存社員も730点とってね」

現行法では、社員を解雇ためには様々な制約があり、TOEICの点数だけで簡単には首にできません。とはいうものの、せっかく新入社員に730点を課したとしても、既に入社済みの圧倒的大多数が英語を使いこなせないのでは意味がありません。入社時に1回だけ点数をとれば良い、なんていう形式的なルールではなく、中の人が継続的に学ぶという会社作りが大切なのではないでしょうか。

私は、大学卒業後に、大学院に進学し、その後キバンインターナショナルに就職したのですが、学部卒時点では710点でした。さすがにそれではまずいと思い院の2年間で英語の勉強にも取り組み、修了時には860を取得できました。就職してからはシステム開発に従事しており英語はあまり勉強できていませんが、2010年1月に935を取得しました。勉強法については、またいつか、記事にまとめるかもしれません。

軽く、自社サービスだけ紹介しておきます。
文法.com
大学入試レベルの動画講義です。大学入試以来しばらく英語から離れてしまっていた人や、そもそも大学入試をしていない人向けにちょうどよいレベルだと思います。坂木先生の授業は分かりやすいです。

WebTOEFL
TOEFLのeラーニングです。TOEICではないですが、上級(TOEIC換算で800↑ぐらい)目指すには良いサービスだと思います。TOEFL受験指導のプロ、葛山先生が、TOEFL向け教材を徹底的に解説しています。

QuizCreatorでTOEIC問題を作成してみました

CATEGORIES eラーニングby.a.takeuchi0 Comments2011.01.24

最近、これまでにも増して、グローバル化の勢いを感じさせるニュースが増えてきたように思います。

例えば・・・

  • SONYは2013年に採用する新卒者のうち30%を外国人に。
  • 武田薬品工業が2013年春入社の新卒採用から、応募条件に英語能力テスト「TOEIC」(990点満点)で730点以上の基準を設けた
  • NTTコミュニケーションズは2012年春から従来の2倍強にあたる約20人の新卒外国人の採用(新卒採用数全体の1割に相当)。

などなど。

グローバル化といえば、英語。英語といえば、TOEIC。

ということで、プログラミング知識不要の問題作成ソフトQuizCreatorでTOEICの問題を作成してみました。以下の画像をクリックすると、問題がスタートします。

▲クリックすると問題がスタートします。(対応ブラウザ:Internet Explorer)

▲クリックすると問題がスタートします。(対応ブラウザ:Internet Explorer)

リーディングの文法問題形式ですが、実際より少し難易度が高いかもしれません。問題数は5問だけですので、腕に覚えのある方はぜひお気軽にチャレンジしてみてください!

問題終了後は、「提出」をクリックしてください。その後、画面右下の「設問リスト表示/非表示」をクリックし、問題番号を選択し「提出」をクリックすれば解説も見ることができます。

●プログラミング知識・作業も不要な試験問題・クイズ作成ソフト

『Quiz Creator』・・・16,800円(税込)

30日間無料お試しダウンロードはこちらからどうぞ。

http://quizcreator.jp/

Eラーニングは通学コースを超えるコストパフォーマンスを出せる!

キバンインターナショナルは『最高の学びをすべてのひとに!』をミッションに掲げ、EラーニングシステムSmartBrainをプラットホームとし、教材作成支援ツールの開発、提供また新たな学びのメディアとしてUstreamによる課金配信サービスを行っております。

企業内教育を中心として導入されてきたEラーニングは、今後教育をビジネスとする団体にも本格的に採用されていくことが予測されます。

Eラーニングは通学コースを超えるコストパフォーマンスを出せるか?が今回のテーマです、手軽な受講料で、教室講義より高い学習生産性が出せるかということです。

資格を取得したいが、なかなかふみ出せない最大の要因は『受講料が高い』『忙しい、時間がない』『近くに通学できる学校がない』だそうです。

まず通学コースで学ぶ人が支出する費用についてですが、これは教育団体のコスト構造とイコールです、教材開発費、講師料、教室家賃、教室運営費、受講生募集費、教材印刷費、教材在庫コスト、教材在庫ロス(教材の改定時発生します)が主なコストです、これに利益を加えたものが受講料として受講生が支払うわけです、通学コースは高いですが、それなりのコストがどうしてもかかってしまうわけですよね。

それから馬鹿にならないのが交通費、私の知人は都内まで週末新幹線で通学し宿泊費を含め毎週5万円もかかったそうです、遠隔地に住まいのかたが、それなりの教育を受けるには負担が大きいですね。

コスト面で考えれば講師料、教室運営もいらない、印刷費、在庫コストのないE-ラーニングは受講料を大幅に低減できることは、当然かもしれません。

一方講義の内容やサービスの面ではどうでしようか?某所でのEラーニングについて受講されたアンケートによれば、メリットとして、A学習時間・場所が自由」であること。好きなときに、自分のペースで受講できる点です。B「繰り返し学習することができる」が挙げられています。
デメリットの上位は、C「受講継続のモチベーションの維持が困難」D「講師や他の受講生とのインタラクティブ性が少ないため、研修自体を淡白に感じる」、さらにE「集合研修に比べて、理解度が下がるのではないか」などです。1人でPCに向かうeラーニングでは、学習の継続は本人の強い意志が大切だ、と経験者は考えているようで、いかにしてモチベーションを保つかが大きな課題といえましょう。

Eについてですが、キバンインターナショナルが協働しているベリタスアカデミーの例をあげますと、板書する時間、講義以外の会話に要する時間などを排除することにより、最先端の電子黒板を使用したEラーニングの講義は3倍の学習生産性を生み出していることが実証されております。

またC,DについてもUstreamの生中継サービスを加えることにより、情報配信、コミュニケーションの補完ができるようになっております。勿論通学コースのように、Face To Faceで講師、受講仲間とやり取りができるわけではないのですが、MixiやFacebookなどのソーシャルネットワークサービスの利用、新しいコミュニケーションメディアのUstreamによるによるスクーリング、セミナー、イベント開催、必要に応じてはリアルなスクーリング、セミナー等ももミックスすることも良いかもしれません。

公務員試験、中小企業診断士などの難関資格も、通学コースに勝るEラーニングで充分挑戦できることになると思います。

キバンインターナショナルは資格取得など、優れたコンテンツをもつ団体、個人のへのEラーニング事業支援を行っております、教材は開発のホームグラウンド、

パンダスタジオに是非いらしてください。

写真はパンダスタジオ近くの古い建物!Once  Upon A Timeというお店なんとも癒される名前です

.faviconを設置しよう

CATEGORIES WordPressby.a.takeuchi0 Comments2011.01.24

皆さん、faviconってご存知でしょうか?名前は聞いたことなくとも、見たことはあると思います。ブラウザのタブや、ブックマークに表示されるアイコンのことです。faviconが適用されていないと、白紙のドキュメントのようなアイコンが表示されてしまいます。些細な違いなのですが、さみしいですね。

favicon適用前

favicon適用前

faviconを適用すると、こんな感じになります。企業のロゴや製品ロゴなど、そのサイトのイメージに合うものがいいですね。

favicon適用後

favicon適用後

favicon作成に用いたサービス

画像編集ソフトを使ってfaviconを作成することもできますが、ウェブサービスで作る方が楽です。今回は以下のサービスを使ってみました。

画像ファイルをアップロードするだけで、faviconにぴったりの画像ファイルが作成できました。favicon.icoという名前のファイルがダウンロードされるので、ドメインのルートにあたるディレクトリにアップロードするだけでOKです。

※ドメインのルートディレクトリ以外にfavicon.icoを設置する場合は以下のサイトを参照ください。
サイトアイコン – favicon.icoの設置方法

先日関西出張だったので、ついでに関西(和歌山と大阪)の書店に立ち寄ってみました。まずは、JR和歌山駅のビル4Fにある、宮井平安堂さんをみてみましょう。
うろうろ・・・・うろろ・・うろ・・うろ。Ustream関連の書棚はありましたが、肝心の「Ustreamで会社をPRする本」は無いみたい。がーん。しかしながら、弊社田中のfacebook本は置いてありました。facebook強いですね。

JR和歌山駅のビル4Fの書店 田中さんのFaceBook本はありました。

 

しかしこれでめげていてはいけません。パソコン関連書籍なら多分ココ!ヨドバシ梅田に来てみました。さてどうでしょうか。

パソコン書籍なら多分ココ!ヨドバシ梅田

 

うろうろ・・・・うろろ・・うろ・・うろ。あれ、パソコン関連書籍のところに無いよ。
うろろ・・うろ・・うろ。
おおー、広告関係の書棚にありました。ビジネス書の棚で、孫社長の本の横に並べてありました。ソフトバンクさんはユーストリームにも出資してますが、だからってことはなく、たまたま隣に並んでるだけでしょうね。

 

ビジネス書のところにありました。

 

では一般書店だとどんな塩梅でしょうか。今度は紀伊國屋書店さんに移動してみましょう。

紀伊國屋書店入り口。いっぱい人が居ます。


うろろ・・おっ検索端末じゃん!あったあった、広告PRの棚にあるようです。ちょっと奥まったところに鎮座しておりますが黄色い表紙は目立ちますね。

 

黄色い表紙の本が並んでいます。

 

引き続き新大阪のブックストア談さんにお邪魔してみます。ベストセラーから専門書まで新大阪で新幹線を利用するビジネスマンに人気(多分)の書店ではどうでしょうか。

新大阪のブックストア談さんにお邪魔


こちらも検索端末でパパっと検索しました。どうも、営業・販促の棚のようですね。

 

縦にならんでおります。


こちらでは、平積みでなく本棚ですが、ありました。

という訳で、「Ustreamで会社をPRする本」は都心の大型書店では、広告とかPRとかそういった関連の棚に並んでいそうです。書店で購入される方はそういったコーナーを観てみてください。(検索端末のあるお店なら検索がオススメですが)


また新たなパンダが、パンダスタジオ(http://pandastudio.tv/)の仲間に加わりましたので紹介します。長谷川さんが。

王です。株式会社キバンインターナショナルのパンダスタジオはオープニング以来、様々な改善が行っています。

社長から、パンダスタジオのCMを作ってみろと言われ、2日間かけて、やっとパンダスタジオのCMを作りました。

動画編集に対して、私がまだ初心者ですので、結構いろいろ分からないところがあります。このパンダスタジオのCMを作っている間に、分からないところに対して、一つずつ解決しながら、自分もすごく勉強になりました。

また、改良をする予定ですが、いったんこれまでできたCMを公開します。

Pythonを使う理由と作った物(ソース付)

CATEGORIES 北海道ラボby.a.takeuchi98 Comments2011.01.21

みなさん、Pythonってご存知でしょうか?
ニシキヘビ。。ではないです。
プログラミング言語のPythonです。

↓Pythonのロゴ。蛇が2匹です。

このPython。日本国内では、それほど知名度は高くないのですが、2010年で最も成長したプログラミング言語にも選ばれるなど、急速に人気の高まりつつある言語です。2011年にはPHPとC++を抜かして3位になれそうな勢いです!では、このPython、どうして急に人気がでてきたのでしょうか?理由は大きくわけて3つあると思います。

Pythonが急に普及し始めた理由

  1. GAEで動作する

    これが最大の理由だと思います。Googleのサーバを使って簡単にサービスを提供できます。1日あたり1GBまでの転送なら、料金は一切かかりません ※1。無料利用分を超えて使った場合も、課金設定(1日当たりの支払い額の上限)を設定するだけで、簡単にサーバを増強できます。ロードバランス、データベースのレプリケーション、そんなことは一切考える必要がありません。全部自動でやってくれます。固定費が不要なので、AmazonEC2なんかより、よっぽど敷居は低いです。

  2. 理解しやすさ

    これには異論が多いと思います。C、Java、PHPなどとは似ても似つかないソースコード。でも、Python、慣れてしまえば読みやすいですよ。Pythonはインデントに縛られた言語です。プログラムの構造と見た目(インデント)が必ず一致しているので、誰が書いても似たようなソースコードになります。慣れないうちは思うように書き進められないかもしれませんが、しばらく使い込めば「読みやすいコード」が自然にかけるようになっているはずです。

  3. 遅さは問題ではなくなった

    Pythonはスクリプト言語です。コンパイル言語と比べると桁違いに遅いです。でも、Webアプリケーションのボトルネックって、言語ではないですよね?多くの場合、データベースアクセスや、ネットワーク通信、マルチメディアファイルのダウンロードがボトルネックです。スクリプト言語の遅さが問題になっていたのは10年前の話です。今は、PHPだって、RoRだって、Pythonだって実用上問題ない速度で動作します。1番にもつながりますが、言語の速度ではなく、スケールアウトするかどうか、つまり、サーバの台数に応じてきちんと性能が伸びるかが問題なのです。

※1 CPUの使用時間(無料分: 6.5時間/日)なども課金対象ですが、通信量制限(無料分: 1GB/日)が最も課金対象になりやすいです。

で、使ってみた。

Pythonを使う○○個の理由とか並べてても、実際に使ってみないと説得力がないので、実際につかってみた。ソースコードも全文貼り付けていますが、初心者が書いたコードなのであまり信用しないで頂けると幸いです。

1. サーバ監視

サーバ監視

サーバ監視

GAEからサーバの監視をしてみた。HTTPリクエストの応答時間を計るだけのシンプルなサービスだが、安定して稼動している。社内のサーバは、Zabbixなどを活用してデータセンタ内からきっちり監視しているが、データセンタと外部との回線の障害などに関しては、外部からの監視が有用だ。(スクリーンショットに掲載したデータは私が個人的に借りているサーバものです)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#!/usr/bin/env python

import cgi
import datetime
import wsgiref.handlers
import urllib
import appengine_utilities.sessions
import os

from datetime import datetime
from datetime import timedelta
from google.appengine.api.urlfetch import fetch
from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.api import images
from google.appengine.api.labs import taskqueue

class Site(db.Model):
  date = db.DateTimeProperty(auto_now_add=True)
  name = db.StringProperty()
  url  = db.URLProperty()

class Log(db.Model):
  date = db.DateTimeProperty(auto_now_add=True)
  response = db.FloatProperty()
  url = db.URLProperty()

class MainPage(webapp.RequestHandler):
  def get(self):
    session = appengine_utilities.sessions.Session()
    if "admin" in session:
      self.response.out.write('<html><head><title>Response Monitor!!</title></head><body>')
      self.response.out.write('<form method="post" action="/"><input type="submit" value="logout"/></form>')
      self.response.out.write('[ <a href="http://blog.elearning.co.jp?s=add&amp;search_404=1">+</a> ]<br />')
      sites = db.GqlQuery("SELECT * FROM Site ORDER BY date DESC LIMIT 10")
      for site in sites:
        self.response.out.write('[ <a href="#" onclick="if(confirm(\'Are you sure to delete it?\'))location.href=\'/delete?id=%s\'">delete</a> ] ' % (site.key()))
        self.response.out.write('<a href="/detail/%s">%s</a> [ %s ]<br />' % (site.url, site.name, site.url))
      self.response.out.write("</body></html>")
    else:
      self.response.out.write('<html><head><title>Response Monitor!!</title></head><body>')
      self.response.out.write('<form method="post" action="/"><input type="password" name="password"/><input type="submit" value="login"/></form>')
      sites = db.GqlQuery("SELECT * FROM Site ORDER BY date DESC LIMIT 10")
      for site in sites:
        self.response.out.write('<a href="/detail/%s">%s</a> [ %s ]<br />' % (site.url, site.name, site.url))
      self.response.out.write("</body></html>")
     
  def post(self):
    session = appengine_utilities.sessions.Session()
    if self.request.get("password") == "hakodate2010":
      session["admin"] = 1
    else:
      if "admin" in session:
        del session["admin"]
    self.redirect('/')

class Detail(webapp.RequestHandler):
  def get(self, key):
    self.response.out.write('<html><head><title>Log for %s</title></head><body>' % urllib.unquote(key))
    self.response.out.write("Log for '%s'" % urllib.unquote(key))
    self.response.out.write("<br />")
    responseMap = {};
    for i in range(0,4):
      query = db.GqlQuery("SELECT * FROM Log WHERE url = :1 ORDER BY date DESC LIMIT %s, 1000" % (1000 * i) , urllib.unquote(key) );
      for log in query:
        log.date+=timedelta(hours=9)
        day = str(log.date)[0:10]
        hour = str(log.date)[11:13]
        if day not in responseMap:
          responseMap[day] = {}
        if hour not in responseMap[day]:
          responseMap[day][hour] = {}
        responseMap[day][hour][log.date] = log.response

    self.response.out.write('<table border=1 style="border-style:solid ">')
    self.response.out.write("<tr><td></td>")
    for day in sorted(list(responseMap)):
      self.response.out.write("<td>")
      self.response.out.write(day)
    self.response.out.write("</td></tr>")

    for hour in range(0,24):
      hour = "%02d" % hour
      self.response.out.write("<tr>")
      self.response.out.write("<td>%s</td>" % hour)
      for day in sorted(list(responseMap)):
        self.response.out.write('<td valign="top">')
        if hour in responseMap[day]:
          limitter = 12
          for log in sorted(list(responseMap[day][hour])):
            limitter = limitter - 1
            if limitter < 0: break
            if responseMap[day][hour][log] == 0:
              self.response.out.write("<font color=red>")
              self.response.out.write(str(log)[14:19] + " ERR ")
            elif responseMap[day][hour][log] < 1.5 and responseMap[day][hour][log] != 0:
              self.response.out.write("<font>")
              self.response.out.write(str(log)[14:19] + " %.3f" % responseMap[day][hour][log])
            elif responseMap[day][hour][log] < 3:
              self.response.out.write('<font color="#FF8135">')
              self.response.out.write(str(log)[14:19] + " %.3f" % responseMap[day][hour][log])
            else:
              self.response.out.write('<font color="#FFBF00">')
              self.response.out.write(str(log)[14:19] + " %.3f" % responseMap[day][hour][log])
            self.response.out.write("</font><br />")
        self.response.out.write("</td>")
      self.response.out.write("</tr>")
    self.response.out.write("</table>")
    self.response.out.write('<div><a href="/">back</a></div>')
    self.response.out.write('</body></html>')

class Cron(webapp.RequestHandler):
  def get(self):
    size = 5
    sites = db.GqlQuery("SELECT * FROM Site ORDER BY date DESC")
    for i in range(0, sites.count(), size):
      params = {}
      for j in range(0, size):
        if i + j >= sites.count():
          break
        params["url"+str(j)] = sites[i+j].url
      taskqueue.add(url='/worker', params = params)

class Worker(webapp.RequestHandler):
  def post(self):
    if(int(self.request.headers.environ['HTTP_X_APPENGINE_TASKRETRYCOUNT']) > 0):
      return
    for key in self.request.arguments():
      try:
        url = self.request.get(key)
        fetchAndLog(url)
      except:
        pass
 
class Add(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
      <form action="/add" method="post" enctype='multipart/form-data'>
        <div>Name: <input type="text" name="name" /></div>
        <div>URL: <input type="text" name="url" /></div>
        <div><input type="submit" value="submit"/></div>
      </form>"""
)
  def post(self):
    if self.request.get('name') != '' or self.request.get('url') != '':
      site = Site()
      site.url = self.request.get('url')
      site.name = self.request.get('name')
      site.put();
    self.redirect('/')

class Delete(webapp.RequestHandler):
  def get(self):
    Site.get(self.request.get('id')).delete()
    self.redirect('/')

def fetchAndLog(url):
  log = Log()
  log.url = url
  log.response = 0.0
  log.put()
  start = datetime.now()
  ret = fetch(url = url, deadline = 30)
  end = datetime.now()
  diff = end - start
  log.response = diff.seconds + diff.microseconds / 1000000.0
  log.put()

application = webapp.WSGIApplication([
  ('/', MainPage),
  ('/add', Add),
  ('/delete', Delete),
  ('/cron', Cron),
  ('/worker', Worker),
  ('/detail/(.*)', Detail),
], debug=True)

def main():
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()

2. ZIPのアップローダー

GAEって静的ファイルおけないんでしょ?ってよく言われるので、アップロードしたZIPファイルを展開して公開するサービスを作ってみた。ファイルはデータストアに保存しているので厳密な意味では静的ファイルではない。(静的ファイルをデプロイすることもできますが、その場合、GAEの管理ツールを使わないとファイルを更新できません。)

zipアップローダー

zipアップローダー

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!/usr/bin/env python

import cgi
import datetime
import wsgiref.handlers

from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.api import images

class Entry(db.Model):
    content = db.StringProperty(multiline=True)
    date = db.DateTimeProperty(auto_now_add=True)
    data = db.BlobProperty()
    contentType = db.StringProperty()

class MainPage(webapp.RequestHandler):
    def get(self):
        self.response.out.write('<html><body>[ <a href="http://blog.elearning.co.jp?s=add&amp;search_404=1">+</a> ]<br />')
        entries = db.GqlQuery("SELECT * FROM Entry ORDER BY date DESC LIMIT 10")
        for entry in entries:
            self.response.out.write('[<a href="#" onclick="if(confirm(\'Are you sure to delete it?\'))location.href=\'/delete?id=%s\'">d</a>][<a href="http://blog.elearning.co.jp?s=edit?id=%s&amp;search_404=1">e</a>] %s<br />' % (entry.key(), entry.key(), cgi.escape(entry.content)))
            if entry.data:
                self.response.out.write('<a href="/image/%s/data"><img src="/image/%s/thumnail"/></a><br />' % (entry.key(),entry.key()))
        self.response.out.write("</body></html>")

class Get(webapp.RequestHandler):
    def get(self, key):
        image = db.get(key)
        if type == 'thumnail':
            self.response.headers['Content-Type'] = 'image/jpeg'
            self.response.out.write(image.thumnail)
        else:
            if image.contentType:
                self.response.headers['Content-Type'] = image.contentType.encode('utf-8')
            else:
                self.response.headers['Content-Type'] = 'image/jpeg'
            self.response.out.write(image.data)

class Add(webapp.RequestHandler):
    def get(self):
        self.response.out.write("""
            <form action="/add" method="post" enctype='multipart/form-data'>
                <div><textarea name="content" rows="3" cols="60"></textarea></div>
                <div><input type="file" name="file"/></div>
                <div><input type="submit" value="submit"/></div>
            </form>"""
)
    def post(self):
        if self.request.get('content') != '' or self.request.get('file') != '':
            entry = Entry()
            entry.content = self.request.get('content')
            if self.request.get('file'):
                entry.data = self.request.POST.get('file').file.read()
                img = images.Image(entry.data)
                img.resize(60, 100)
                entry.contentType = self.request.body_file.vars['file'].headers['content-type']
            entry.put();
        self.redirect('/')

class Edit(webapp.RequestHandler):
    def get(self):
        post = Entry.get(self.request.get('id'))
        self.response.out.write("""
            <form action="/edit?id=%s" method="post">
                <div><textarea name="content" rows="3" cols="60">%s</textarea></div>
                <div><input type="submit" value="submit"/></div>
            </form>"""
% (self.request.get('id'), post.content))
    def post(self):
        entry = Entry.get(self.request.get('id'))
        entry.content = self.request.get('content')
        entry.put()
        self.redirect('/')

class Delete(webapp.RequestHandler):
    def get(self):
        Entry.get(self.request.get('id')).delete()
        self.redirect('/')

application = webapp.WSGIApplication([
    ('/', MainPage),
    ('/add', Add),
    ('/get/([-\w]+)', Get),
], debug=True)

def main():
    wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
    main()

3. ブログシステム

ブログシステムを作ってみた。一覧表示ページ、個別記事ページ、タグページぐらいしかないが、一般的な用途ならこれぐらいでいい気がする。RSSを配信しているので、FeedTweetなどを使ってTwttterに更新履歴を流したりもできる。Wordpressとなどと比べると機能も少ないし、デザインもテンプレート化できていないが、レスポンスはよいし、満足して使っている。

python-blog

python-blog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.ext import db
from google.appengine.api import users
import urllib, datetime, re
step = 10
title = "Python blog system"

class AuthHandler(webapp.RequestHandler):
  def get(self, key = ""):
    if users.get_current_user() == None:
      self.write("<a href="%s">Sign in or register</a>." % users.create_login_url("/admin"))
    elif users.is_current_user_admin() != True:
      self.write('Your account %s is not admin. <a href="%s">Log out</a> and log in with an admin account.' % (users.get_current_user(), users.create_logout_url("/admin")))
    else:
      if key:
        self.get2(key)
      else:
        self.get2()
  def post(self, key = ""):
    if users.is_current_user_admin():
      if key:
        self.post2(key)
      else:
        self.post2()
  def write(self, str):
    self.response.out.write(str)

class MainHandler(AuthHandler):
  def get(self, pageStr):
    try:
      page = int(pageStr)
    except ValueError:
      page = 0
    printHeader(self, title)
    self.write('<h1><a href="/">%s</a></h1>' % title)
    if users.is_current_user_admin():
      self.write('<h2>[<a href="http://blog.elearning.co.jp?s=&amp;search_404=1">New</a>] [<a href="%s">Log out</a>]</h2>'  % users.create_logout_url("/"))
    entries = Entry.all().order("-datetime").fetch(step + 1, page * step)
    for entry in entries[:step]:
      printEntry(self, entry)
    if len(entries) > step:
      self.write('[ <a href="/%d"> Next %d</a> ]' % (page + 1, step))
    if page > 0:
      self.write('[ <a href="/%d"> Prev %d</a> ]' % (page - 1, step))
    printFooter(self)

class RSSHandler(AuthHandler):
  def get(self, pageStr):
    self.write(
u"""< ?xml version="1.0" encoding="utf-8"?>
<rdf:rdf xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns="http://purl.org/rss/1.0/">
  <channel rdf:about="http://python-blog-system.appspot.com/">
    <title>%(title)s</title>
    <link>http://python-blog-system.appspot.com</link>
    <description>%(title)s</description>
    <dc:language>ja</dc:language>
    <dc:creator>N/A</dc:creator>
    <dc:date>%(now)s</dc:date>
  </channel>"""
% {'now' : '2010-12-31T16:57:12+09:00', 'title' : title})
    for entry in Entry.all().order("-datetime").fetch(30):
      self.write("""  <item rdf:about="http://python-blog-system.appspot.com/entry/%(key)s">
    <title>%(title)s</title>
    <link>http://python-blog-system.appspot.com/entry/%(key)s</link>
    <description>%(body)s</description>
    <dc:date>%(datetime)s</dc:date>
  </item>
"""
% {"key" : entry.key(), "title" : h(entry.title), "body" : h(entry.body), "datetime" : entry.formattedDatetimeInJST})
    self.write("</rdf:rdf>")

class AdminHandler(AuthHandler):
  def get2(self, key):
    self.redirect("/")

class PostHandler(AuthHandler):
  def get2(self,key = ""):
    entry = Entry.get(key) if key != '' else Entry()
    title = "Edit Entry" if key!= '' else "New Entry"
    deleteButton = """<input type="button" value="delete" onclick="if(confirm('Are you sure to delete it?'))location.href='/delete/%s'"/>""" % key if key!= '' else ''
    printHeader(self, title)
    self.write("<h1>%s</h1>" % title)
    self.write(u"""<form method="post" action="/post/%(key)s">
<h2>タイトル</h2><input type="text" name="title" value="%(title)s" style="width:400px"/>
<h2>本文</h2><textarea name="body" style="width:400px;height:300px;">%(body)s</textarea>
<h2>タグ</h2><input type="text" name="tags" value="%(tags)s" style="width:400px"/>
<h2>画像 [<a href="http://blog.elearning.co.jp?s=uploader&amp;search_404=1" target="_blank">uploader</a>]</h2>
<div>%(deleteButton)s<input type="submit" value="submit"/></div></form>"""
% {"key" : key, "title" : entry.title, "body" : entry.body, "tags" : entry.tagStr(), "deleteButton":deleteButton})
    printFooter(self)
  def post2(self, key = ""):
    if self.request.get("title") != '' and self.request.get("body") != '':
      entry = Entry.get(key) if key != '' else Entry()
      entry.title = self.request.get("title")
      entry.body = self.request.get("body")
      entry.tags = []
      for tagStr in self.request.get('tags').replace(u' ',' ').replace('  ',' ').replace(',',' ').split(' '):
        tag = Tag.all().filter("tag =", tagStr).get()
        if tag == None:
          tag = Tag(tag = tagStr)
          tag.put()
        entry.tags.append(tag.key())
      entry.put()
    self.redirect('/')

class PostCommentHandler(AuthHandler):
  def post(self, key):
    if self.request.get("comment") != '':
      Comment(
        entry = Entry.get(key),
        comment = self.request.get("comment"),
        delpass = self.request.get("delpass"),
        nickname = self.request.get("nickname")
      ).put()
    self.redirect("/entry/%s" % key)

class DeleteHandler(AuthHandler):
  def get2(self, key):
    db.delete(Entry.get(key))
    self.redirect('/')

class DeleteCommentHandler(AuthHandler):
  def post(self, key):
    comment = Comment.get(key)
    entry_key = comment.entry.key()
    self.write(self.request.get("delpass"))
    self.write(comment.delpass)
    if self.request.get("delpass") == comment.delpass:
      db.delete(comment)
    self.redirect('/entry/%s' % entry_key)

class TagHandler(AuthHandler):
  def get(self, key):
    tagStr = urllib.unquote(key).decode('utf-8')
    title = "Python blog system / %s" % tagStr
    printHeader(self, title);
    tag = Tag.all().filter("tag =", tagStr).get()
    self.write('<h1><a href="/">Python blog system</a> / %s</h1>' % h(tagStr))
    if tag:
      for entry in tag.entries:
        printEntry(self, entry)
    else:
      self.write("<h2>Tag %s does not exist</h2>" % h(tagStr))
    printFooter(self)

class EntryHandler(AuthHandler):
  def get(self, key):
    entry = Entry.get(key)
    printHeader(self, "%s / %s" % (title, entry.title));
    self.write('<h1><a href="/">%s</a></h1>' % title)
    printEntry(self, entry, commentDetail = True)
    printFooter(self)

class UploaderHandler(AuthHandler):
  def get2(self, key):
    printHeader(self, "Uploader")
    self.write("<h1>Uploader</h1>")
    for image in Image.all():
      self.write('<h2><img src="/image/%(key)s"/><br /><input type="text" value="[img:%(key)s]" style="width:300px;font-size:x-small"/><input type="button" value="delete" onclick="location.href=\'/deleteImage/%(key)s\'"/></h2>' % {"key":image.key()})
    self.write(u'<h2><form action="/uploader" enctype="multipart/form-data" method="post"><input type="file" name="file"/><input type="submit" value="Upload"/></form></h2>')
    printFooter(self)
  def post2(self, key):
    if self.request.get('file'):
      self.write("hoge")
      image = Image()
      image.image = self.request.POST.get('file').file.read()
      image.contentType = self.request.body_file.vars['file'].headers['content-type']
      image.put()
    self.redirect('/uploader')

class DeleteImageHandler(AuthHandler):
  def get2(self, key):
    Image.get(key).delete()
    self.redirect('/uploader')

class ImageHandler(AuthHandler):
  def get(self, key):
    image = Image.get(key)
    self.response.headers['Content-Type'] = image.contentType.encode('utf-8')
    self.response.out.write(image.image)

def printEntry(self, entry, commentDetail = False):
  user = users.get_current_user()
  if user:
    editLink = '[<a href="/post/%s">edit</a>]' % entry.key()
  else:
    editLink = ''
  self.write('<div class="entry">\n<div class="entryHeader">\n')
  self.write('<h2 class="title"><a href="/entry/%(key)s">%(title)s</a> %(editLink)s</h2> <div class="entryDate">%(datetime)s</div>'
    % {"key" : entry.key(), "title" : h(entry.title), "editLink" : editLink, "datetime" : entry.formattedDatetimeInJST})
  self.write('</div>\n')#header
  self.write(replaceImages(linkURLs(nl2br(h(entry.body)))));
  self.write('\n<div class="entryFooter">tag:\n')
  for tag in entry.tags:
    tagObj = Tag.get(tag)
    self.write('<a href="/tag/%s"><span class="tag">%s</span></a>\n' % (urllib.quote_plus(tagObj.tag.encode('utf-8')) ,h(tagObj.tag)))
  if commentDetail:
    self.write(u'<h2>コメント</h2><div class="comments"><a name="comments">\n')
    for comment in entry.comments.order('datetime'):
      if comment.nickname == None or comment.nickname == "":
        comment.nickname = "Anonymous"
      delbutton = u"""
        <div style="float:right">
          <form method="post" name="form" action="/deleteComment/%(key)s">
          <input type="text" name="delpass" class="delcommentpassword"/>
          <input type="button" onclick="if(confirm('本当に削除しますか?'))form.submit()" value="削除" class="delcommentbutton"/>
          </form>
        </div><br clear="all"/>"""
% {"key":comment.key()}
      self.write('<h3 class="comment">%s: %s %s</h3>' % (comment.nickname, comment.comment, delbutton))
    self.write(u'<div style="width:84px;float:left;font-size:xx-small;position:relative;top:6px;">名前</div>')
    self.write(u'<div style="width:184px;float:left;font-size:xx-small;position:relative;top:6px;">コメント</div>')
    self.write(u'<div style="width:100px;float:left;font-size:xx-small;position:relative;top:6px;">削除パス</div>')
    self.write(u'<br clear="all"/>')
    self.write(u'<form action="/postComment/%s" method="post" style="padding:0">' % entry.key())
    self.write(u'<input type="text" name="nickname" style="width:80px;"/>')
    self.write(u'<input type="text" name="comment" style="width:180px;"/>')
    self.write(u'<input type="text" name="delpass" style="width:50px;"/>')
    self.write(u'<input type="submit" value="投稿" style="width:50px"/>')
    self.write("</form></a></div>\n")
  else:
    self.write(u'<a href="/entry/%s#comments">コメント(%s)</a>\n' % (entry.key(), entry.comments.count()))
  self.write("</div>\n")#footer
  self.write("</div>\n")#entry

def urlReplacer(match, limit = 45):
  return '<a href="%s" target="_blank">%s</a>' % (match.group(), match.group()[:limit] + ('...' if len(match.group()) > limit else ''))

def linkURLs(str):
  return re.sub(r'([^"]|^)(https?|ftp)(://[\w:;/.?%#&=+-]+)', urlReplacer, str)

def replaceImages(str):
  return re.sub(r'\[img:(.*)\]', r'<img src="http://blog.elearning.co.jp?s=\1&amp;search_404=1" style="max-width:400px"/>', str)

def printHeader(self, title):
  self.write("""< ?xml version="1.0" encoding="UTF-8"?>
< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
  <link rel="alternate" type="application/rss+xml" title="RSS" href="rss"/>
  <meta http-equiv="content-script-type" content="text/javascript"/>
  <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
  <title>%s</title>
  <link rel="stylesheet" type="text/css" href="/css/style.css"/>
  <meta name = "viewport" content = "width=420"/>
  <script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-20245912-2']);
  _gaq.push(['_trackPageview']);
  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
  </script>"""
% (h(title)))
  self.write("</head>\n<body>\n");

def printFooter(self):
  self.write(u'<div>developed by <a href="http://php6.jp/python/">python練習帳</a></div>\n</body>\n</html>')

def nl2br(str):
  return str.replace('\r\n','\n').replace('\n','<br />\n')

class Entry(db.Model):
  title = db.StringProperty(default = "")
  body = db.TextProperty(default = "")
  tags = db.ListProperty(db.Key)
  datetime = db.DateTimeProperty(auto_now_add = True)
  @property
  def formattedDatetimeInJST(self):
    return (self.datetime + datetime.timedelta(hours=9)).strftime("%Y-%m-%d %H:%M:%S")
  def tagStr(self):
    return " ".join([Tag.get(x).tag for x in self.tags])

class Tag(db.Model):
  tag = db.StringProperty()
  @property
  def entries(self):
    return Entry.all().filter('tags', self.key()).order('-datetime')

class Comment(db.Model):
  comment = db.TextProperty(default = "")
  entry = db.ReferenceProperty(Entry, collection_name = 'comments')
  user = db.UserProperty()
  datetime = db.DateTimeProperty(auto_now_add = True)
  delpass = db.TextProperty()
  nickname = db.TextProperty()

class Image(db.Model):
  image = db.BlobProperty()
  contentType = db.StringProperty()

def main():
  application = webapp.WSGIApplication([
    ('/tag/(.*)', TagHandler),
    ('/entry/(.*)', EntryHandler),
    ('/admin/?(.*)', AdminHandler),
    ('/postComment/?(.*)', PostCommentHandler),
    ('/post/?(.*)', PostHandler),
    ('/rss/?(.*)', RSSHandler),
    ('/deleteComment/?(.*)', DeleteCommentHandler),
    ('/deleteImage/(.*)', DeleteImageHandler),
    ('/delete/?(.*)', DeleteHandler),
    ('/uploader/?(.*)', UploaderHandler),
    ('/image/(.*)', ImageHandler),
    ('/(.*)', MainHandler)
  ], debug=True)
  util.run_wsgi_app(application)

def h(html):
  return html.replace('&','&amp;').replace('< ','&lt;').replace('>','&gt;').replace('"','&quot;')

if __name__ == '__main__':
  main()

おわりに

Pythonの良さをざっと紹介しましたが、どのように感じられましたでしょうか?C、Java、PHPなどに慣れた人にとっては異質なソースコードだと思います。でも、一度慣れてしまうと、すごく合理的で分かりやすい言語だと思います。このブログにPython関連の記事を書き続けるのは気が引けますので、興味を持たれた方はPython練習帳をご覧いただければと思います。

皆さん、こんにちは。今回は、LectureMAKERの機能や使い方が一目でわかる「LectureMAKERを学ぶ講座」のWebページ(http://lecturemaker.jp/?page_id=3449)を公開しましたので、ご紹介いたします。

1.「製品概要」をクリックします。

2.LectureMAKERを学ぶ講座をクリックします。

3.公開されたPart1の画像をクリックし、InternetExplorer上で再生します。


本教材は、LectureMAKERのビューア形式で保存されています。Part1 のコンテンツ内容は以下となります。(LectureMAKERのビューアは、ActiveXを使うため、InternetExplorer のみ再生可能です)

Part 1. LectureMAKER はじめる

1. LectureMAKERとは?
2.活用分野
3.実務上の活用例
4.LectureMAKERの機能

Part 1. LectureMAKER はじめる

Part 1. LectureMAKER はじめる(クリックで再生)

また、Prat2~3までは、2月中の公開、Part4 ~5までは、3月中の公開と予定しております。

電車を長い時間乗っていると急に時間が勿体ないと思い、何か本が読みたいと思ったことありませんか。
私は、最近個人的に本にはまっていますが、小説や専門書籍も読んだりします。
そのようなことで、弊社の同じ韓国スタッフが買って来た本を簡単にご紹介したいと思います。

「知識デザインの実務」という本です。本の内容は、簡単(一部)に以下の通りです。
 情報通信技術及びネットの発達で知識の時代に入り、今は、知識は水のように必要な場所だと
どこでも接することが出来ています。しかしながら、知識が溢れる時代ですが、自分に合う正しい知識を探すのは、決して簡単ではないです。
自分に合う知識を正しく提供された時こそ、その価値を認められます。
知識を利用するには、正しく使えるように再加工する過程をファッションのようにデザインするとどうなるんだろう。
1.知識もファッションのように、デザインする時代、2.右脳と左脳の活動の融合、3.実用主義の志向
【知識サービスの発展戦略】
1.感性的な知識サービスの行動化で国家の競争力を強化する2.知識サービスの発展展望_知識サービスの意味や知識サービスの基盤のeラーニングの活性化戦略など

読んでいくうちに、本の内容をしっかり理解できそうな感じがしました。
何より、正しい情報を受け入れ、有効的に活用することが大事ですね。

▼知識デザインの実務の本

  • 製品・サービス
    PC、iPhone対応のeラーニングシステム。20名まで無料でASPサービスを利用できます
    PC、iPhone対応のeラーニング学習管理システム(LMS)【SmartBrain】
    http://smartbrain.info/
    PC、iPhone対応のeラーニングシステム。ユーザ数無制限のASPコースをご用意。


    eラーニングポータルサイト【elearning.co.jp】
    http://elearning.co.jp/
    eラーニング専門企業(株)キバンインターナショナルの製品を紹介しています。


    コンテンツビジネス支援パック
    http://contentsbank.jp/

    Ustream配信、動画コンテンツ制作、セミナーにご利用いただけるレンタルスタジオ
    Ustreamレンタルスタジオ「パンダスタジオ」
    http://pandastudio.tv/

    eラーニング専門企業(株)キバンインターナショナルのスタッフが、eラーニングに関する情報・最新事情をBlogでご紹介。月50本程度の情報発信を行っています。
    ブログ「blog.eラーニング.co.jp」
    http://blog.elearning.co.jp/

  • アーカイブ
  • カテゴリー
  • Amazon
  • タグ