diff --git a/.gitignore b/.gitignore index a8a40ef..986f656 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ yarn-error.log* public/png *.xml +freespeech_walle # Created by https://www.gitignore.io/api/python diff --git a/config/webpack.config.flask.js b/config/webpack.config.flask.js index 0fd5168..c94511e 100644 --- a/config/webpack.config.flask.js +++ b/config/webpack.config.flask.js @@ -254,6 +254,32 @@ module.exports = { new ManifestPlugin({ fileName: 'asset-manifest.json', }), + new SWPrecacheWebpackPlugin({ + // By default, a cache-busting query parameter is appended to requests + // used to populate the caches, to ensure the responses are fresh. + // If a URL is already hashed by Webpack, then there is no concern + // about it being stale, and the cache-busting can be skipped. + dontCacheBustUrlsMatching: /\.\w{8}\./, + filename: 'service-worker.js', + logger(message) { + if (message.indexOf('Total precache size is') === 0) { + // This message occurs for every build and is a bit too noisy. + return; + } + console.log(message); + }, + minify: true, + // For unknown URLs, fallback to the index page + navigateFallback: publicUrl + '/index.html', + // Ignores URLs starting from /__ (useful for Firebase): + // https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219 + navigateFallbackWhitelist: [/^(?!\/__).*/], + // Don't precache sourcemaps (they're large) and build asset manifest: + staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/], + // Work around Windows path issue in SWPrecacheWebpackPlugin: + // https://github.com/facebookincubator/create-react-app/issues/2235 + stripPrefix: paths.appBuild.replace(/\\/g, '/') + '/', + }), new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), new WriteFilePlugin() ], diff --git a/get_morph_rule.py b/get_morph_rule.py new file mode 100644 index 0000000..4b6838c --- /dev/null +++ b/get_morph_rule.py @@ -0,0 +1,168 @@ +import sys +import os + +sys.path.append(os.getcwd()+'/content-engine') +import pluralize_en +import pattern.en + + +def noun_morphology(word): + morph = {} + morph['PLR'] = pluralize_en.pluralize(word) + return morph + +def adjective_morphology(word): + morph = {} + morph['SUP'] = pattern.en.superlative(word) + morph['CMP'] = pattern.en.comparative(word) + return morph + +def verb_morphology(word): + morph = {} + lex = pattern.en.lexeme(word) + morph['PAS'] = lex[0] + morph['PTP'] = lex[0] + if len(lex) >= 2: + morph['3PS&PRS'] = lex[1] + if len(lex) >= 3: + morph['GER'] = lex[2] + if len(lex) >= 4: + morph['PAS'] = lex[3] + morph['PTP'] = lex[3] + if len(lex) >= 5: + morph['PTP'] = lex[4] + return morph + +def adverb_morphology(word): + morph = {} + return morph + +def morphology(name, pos): + if pos == 'n': + return noun_morphology(name) + elif pos == 'v': + return verb_morphology(name) + elif pos == 's' or pos == 'a': + return adjective_morphology(name) + elif pos == 'r': + return adverb_morphology(name) + else: + raise Exception + +def getMorphRules(): + f = open('content-engine/morphology.txt','r').readlines() + for idx,rule in enumerate(f): + f[idx] = rule.split(' ') + for idx,rule in enumerate(f): + if len(f[idx]) >= 3: + f[idx][2] = f[idx][2].strip() + rules = {} + for idx,rule in enumerate(f): + if len(rule) >= 3: + rules[rule[0]] = rule[2] + else: + rules[rule[0]] = {} + for i in rules: + if '#' in rules[i]: + rules[i] = rules[i].split('#')[0].strip() + for i in rules: + rules[i]=rules[i].split(';') + for i in rules: + rule_params = {} + for j in rules[i]: + j = j.split(':') + if len(j) >= 2: + rule_params[j[0]] = j[1] + rules[i] = rule_params + return rules + +def is_number(s): + try: + int(s) + return True + except ValueError: + return False + +def subRuleMatch(morph_dict_sub,sub_rule,word): + sub_rule = sub_rule.split('>') + if len(sub_rule) < 2: + sub_rule.append('') + if is_number(sub_rule[0]): + num = int(sub_rule[0]) + if num == 0: + if word + sub_rule[1] != morph_dict_sub: + return False + else: + if word[:-1*num] + sub_rule[1] != morph_dict_sub: + return False + return True + if '^' in sub_rule[0]: + if sub_rule[1] + ' ' + word != morph_dict_sub: + return False + return True + if not word.endswith(sub_rule[0]): + return False + if word[:-1*len(sub_rule[0])] + sub_rule[1] != morph_dict_sub: + return False + return True + +def ruleMatch(morph_dict,morph_rule,word): + for parameter in morph_rule: + if parameter not in morph_dict: + return False + if not subRuleMatch(morph_dict[parameter],morph_rule[parameter],word): + return False + return True + +def morphRule(name, pos, morph_dict): + # morph_dict = morphology(name, pos) + + morph_rules = getMorphRules() + specified_params = [] + matching_rules = [] + + for rule in morph_rules: + specified_params = [] + if rule != 'M0': + if ruleMatch(morph_dict,morph_rules[rule],name): + if len(morph_rules[rule]) < len(morph_dict): + for i in morph_dict: + if i not in morph_rules[rule]: + specified_params.append(str(i)+','+morph_dict[i]) + matching_rules.append([rule,specified_params]) + + if len(matching_rules) != 0: + matching_rules.sort() + return matching_rules[0][0], matching_rules[0][1] + + rule = 'M0' + if len(morph_rules[rule]) < len(morph_dict): + for i in morph_dict: + if i not in morph_rules[rule]: + specified_params.append(str(i)+','+morph_dict[i]) + + return rule, specified_params + +def get_morph_rule(word,pos,morph_dict): + for m in morph_dict: + morph_dict[m] = morph_dict[m].lower() + m,r = morphRule(word.lower(),pos.lower(),morph_dict) + return m + +def get_morph(word,p): + syn_pos_map = {"n":"n","j":"a","v":"v","a":"r"} + pos = syn_pos_map[p.lower()] + morph_dict = morphology(word,pos) + for m in morph_dict: + morph_dict[m] = morph_dict[m].lower() + m,params = morphRule(word.lower(),pos,morph_dict) + morphs = {} + morphs["morphclass"] = m + for r in params: + [k,v] = r.split(",") + morphs[k] = v + return morphs + +if __name__ == '__main__': + print get_morph_rule("spell","v",{'3PS&PRS':'spells','PAS':'spellt','GER':'spelling','PTP':'spellt'}) + print get_morph_rule("french fry","n",{'PLR':'french fries'}) diff --git a/scripts/flask.js b/scripts/flask.js index 819ce34..07087bb 100644 --- a/scripts/flask.js +++ b/scripts/flask.js @@ -116,7 +116,7 @@ startWebPackDevServer(()=>{ // child_process.spawn('webpack',['--watch','--config','config/webpack.config.flask.js'],{ // stdio:'inherit' // }); - child_process.spawn('python',['walle-server.py'],{ + child_process.spawn('python',['walle_server.py'],{ stdio:'inherit' }); }); diff --git a/src/LexEdit.tsx b/src/LexEdit.tsx index f392278..34953b4 100644 --- a/src/LexEdit.tsx +++ b/src/LexEdit.tsx @@ -11,6 +11,16 @@ import { } from 'semantic-ui-react'; const { Box } = require('reflexbox'); +const serialize = function(obj: any) { + var str = []; + for(var p in obj){ + if (obj.hasOwnProperty(p)) { + str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p])); + } + } + return str.join('&'); +}; + export class LexEdit extends React.Component { imageRoot = '/png/'; constructor(props: any) { @@ -90,9 +100,21 @@ export class LexEdit extends React.Component { let lexItem = this.props.lexItem; this.setState({ lexItem }); } + private handleOnLoad(event: any) { // this.props.load(this.state.lexItem) - console.log('loading from server'); + let lexItem = this.props.lexItem; + let word = _.get(lexItem, this.props.fieldMetaMap.label.lens, ''); + let pos = _.get(lexItem, this.props.fieldMetaMap.pos.lens, ''); + let args = serialize({word,pos}); + fetch('/morph?'+args) + .then((response) => response.text()) + .then((jsonMorph) => { + console.log(jsonMorph); + }) + .catch((e) => { + console.log('errored :', e); + }); } private handleOnChange(event: any) { diff --git a/walle-server.py b/walle_server.py similarity index 65% rename from walle-server.py rename to walle_server.py index beadb83..ab2b838 100644 --- a/walle-server.py +++ b/walle_server.py @@ -1,6 +1,7 @@ -from flask import Flask,send_from_directory +from flask import Flask,send_from_directory,request app = Flask(__name__,static_url_path='',static_folder='build') -import requests +from freespeech_walle.get_morph_rule import get_morph +import json @app.route('/') def walle_index(): @@ -11,7 +12,14 @@ def walle_index(): def walle_test(): return "test" +@app.route('/morph') +def walle_morph(): + word = request.args.get('word') + pos = request.args.get('pos') + return json.dumps(get_morph(word,pos)) + # hmr streaming +# import requests # from flask import Response,stream_with_context # @app.route('/',methods=['GET','POST']) # def walle_hmr(url):