Spaces:
				
			
			
	
			
			
		Sleeping
		
	
	
	
			
			
	
	
	
	
		
		
		Sleeping
		
	Upload 3 files
Browse files- Dockerfile +17 -0
 - app (1).py +121 -0
 - requirements (1).txt +1 -0
 
    	
        Dockerfile
    ADDED
    
    | 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
| 
         | 
|
| 1 | 
         
            +
            # Dockerfile
         
     | 
| 2 | 
         
            +
            FROM python:3.9-slim
         
     | 
| 3 | 
         
            +
             
     | 
| 4 | 
         
            +
            WORKDIR /app
         
     | 
| 5 | 
         
            +
             
     | 
| 6 | 
         
            +
            # 依存関係のインストール
         
     | 
| 7 | 
         
            +
            COPY requirements.txt .
         
     | 
| 8 | 
         
            +
            RUN pip install --no-cache-dir -r requirements.txt
         
     | 
| 9 | 
         
            +
             
     | 
| 10 | 
         
            +
            # アプリの全ファイルをコピー
         
     | 
| 11 | 
         
            +
            COPY . .
         
     | 
| 12 | 
         
            +
            RUN touch weak_phrases.json && chmod 666 weak_phrases.json
         
     | 
| 13 | 
         
            +
             
     | 
| 14 | 
         
            +
            # Hugging Face Spaces ではポート 7860 を使用する
         
     | 
| 15 | 
         
            +
            EXPOSE 7860
         
     | 
| 16 | 
         
            +
             
     | 
| 17 | 
         
            +
            CMD ["python", "app.py"]
         
     | 
    	
        app (1).py
    ADDED
    
    | 
         @@ -0,0 +1,121 @@ 
     | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
| 
         | 
|
| 1 | 
         
            +
            import json, random, os
         
     | 
| 2 | 
         
            +
            from flask import Flask, jsonify, request, send_from_directory
         
     | 
| 3 | 
         
            +
             
     | 
| 4 | 
         
            +
            app = Flask(__name__)
         
     | 
| 5 | 
         
            +
             
     | 
| 6 | 
         
            +
            DATA_FILE = "sum.json"       # 全フレーズの JSON ファイル
         
     | 
| 7 | 
         
            +
            WEAK_FILE = "weak_phrases.json"   # 苦手フレーズ用の JSON ファイル
         
     | 
| 8 | 
         
            +
             
     | 
| 9 | 
         
            +
            def load_json(file_path):
         
     | 
| 10 | 
         
            +
                if os.path.exists(file_path):
         
     | 
| 11 | 
         
            +
                    with open(file_path, "r", encoding="utf-8") as f:
         
     | 
| 12 | 
         
            +
                        return json.load(f)
         
     | 
| 13 | 
         
            +
                else:
         
     | 
| 14 | 
         
            +
                    return {"phrases": []}
         
     | 
| 15 | 
         
            +
             
     | 
| 16 | 
         
            +
            def save_json(file_path, data):
         
     | 
| 17 | 
         
            +
                with open(file_path, "w", encoding="utf-8") as f:
         
     | 
| 18 | 
         
            +
                    json.dump(data, f, indent=4, ensure_ascii=False)
         
     | 
| 19 | 
         
            +
             
     | 
| 20 | 
         
            +
            def get_all_phrases():
         
     | 
| 21 | 
         
            +
                data = load_json(DATA_FILE)
         
     | 
| 22 | 
         
            +
                phrases = []
         
     | 
| 23 | 
         
            +
                for category in data["phrases"]:
         
     | 
| 24 | 
         
            +
                    for phrase in category["phrases"]:
         
     | 
| 25 | 
         
            +
                        phrases.append({
         
     | 
| 26 | 
         
            +
                            "category": category.get("category_english", ""),
         
     | 
| 27 | 
         
            +
                            "category_japanese": category.get("category_japanese", ""),
         
     | 
| 28 | 
         
            +
                            "phrase": phrase.get("phrase", ""),
         
     | 
| 29 | 
         
            +
                            "description": phrase.get("description", ""),
         
     | 
| 30 | 
         
            +
                            "example": phrase.get("example", "")
         
     | 
| 31 | 
         
            +
                        })
         
     | 
| 32 | 
         
            +
                return phrases
         
     | 
| 33 | 
         
            +
             
     | 
| 34 | 
         
            +
            def get_phrases_by_category(category_name):
         
     | 
| 35 | 
         
            +
                data = load_json(DATA_FILE)
         
     | 
| 36 | 
         
            +
                for category in data["phrases"]:
         
     | 
| 37 | 
         
            +
                    if category.get("category_english", "").lower() == category_name.lower() or category.get("category_japanese", "") == category_name:
         
     | 
| 38 | 
         
            +
                        return category["phrases"]
         
     | 
| 39 | 
         
            +
                return []
         
     | 
| 40 | 
         
            +
             
     | 
| 41 | 
         
            +
            def get_thanks_phrases():
         
     | 
| 42 | 
         
            +
                data = load_json(DATA_FILE)
         
     | 
| 43 | 
         
            +
                phrases = []
         
     | 
| 44 | 
         
            +
                for category in data["phrases"]:
         
     | 
| 45 | 
         
            +
                    # この組み合わせのみ対象
         
     | 
| 46 | 
         
            +
                    if category.get("category_english") == "Thanks for..." and category.get("category_japanese") == "〜に感謝する":
         
     | 
| 47 | 
         
            +
                        for phrase in category["phrases"]:
         
     | 
| 48 | 
         
            +
                            phrases.append({
         
     | 
| 49 | 
         
            +
                                "category": category.get("category_english", ""),
         
     | 
| 50 | 
         
            +
                                "category_japanese": category.get("category_japanese", ""),
         
     | 
| 51 | 
         
            +
                                "phrase": phrase.get("phrase", ""),
         
     | 
| 52 | 
         
            +
                                "description": phrase.get("description", ""),
         
     | 
| 53 | 
         
            +
                                "example": phrase.get("example", "")
         
     | 
| 54 | 
         
            +
                            })
         
     | 
| 55 | 
         
            +
                return phrases
         
     | 
| 56 | 
         
            +
             
     | 
| 57 | 
         
            +
            def get_random_phrase(phrases):
         
     | 
| 58 | 
         
            +
                if not phrases:
         
     | 
| 59 | 
         
            +
                    return None
         
     | 
| 60 | 
         
            +
                return random.choice(phrases)
         
     | 
| 61 | 
         
            +
             
     | 
| 62 | 
         
            +
            @app.route("/phrases", methods=["GET"])
         
     | 
| 63 | 
         
            +
            def phrases():
         
     | 
| 64 | 
         
            +
                mode = request.args.get("mode", "random")
         
     | 
| 65 | 
         
            +
                if mode == "weak":
         
     | 
| 66 | 
         
            +
                    weak_data = load_json(WEAK_FILE)
         
     | 
| 67 | 
         
            +
                    phrase_list = weak_data.get("phrases", [])
         
     | 
| 68 | 
         
            +
                elif mode == "category":
         
     | 
| 69 | 
         
            +
                    category = request.args.get("category", "")
         
     | 
| 70 | 
         
            +
                    phrase_list = get_phrases_by_category(category)
         
     | 
| 71 | 
         
            +
                elif mode == "thanks":
         
     | 
| 72 | 
         
            +
                    phrase_list = get_thanks_phrases()
         
     | 
| 73 | 
         
            +
                else:
         
     | 
| 74 | 
         
            +
                    phrase_list = get_all_phrases()
         
     | 
| 75 | 
         
            +
                return jsonify(phrase_list)
         
     | 
| 76 | 
         
            +
             
     | 
| 77 | 
         
            +
            @app.route("/add_weak", methods=["POST"])
         
     | 
| 78 | 
         
            +
            def add_weak():
         
     | 
| 79 | 
         
            +
                data = request.get_json()
         
     | 
| 80 | 
         
            +
                phrase_text = data.get("phrase")
         
     | 
| 81 | 
         
            +
                if not phrase_text:
         
     | 
| 82 | 
         
            +
                    return jsonify({"error": "フレーズが入力されていません"}), 400
         
     | 
| 83 | 
         
            +
             
     | 
| 84 | 
         
            +
                all_phrases = get_all_phrases()
         
     | 
| 85 | 
         
            +
                phrase_obj = next((p for p in all_phrases if p["phrase"] == phrase_text), None)
         
     | 
| 86 | 
         
            +
                if not phrase_obj:
         
     | 
| 87 | 
         
            +
                    return jsonify({"error": "指定されたフレーズが見つかりません"}), 404
         
     | 
| 88 | 
         
            +
             
     | 
| 89 | 
         
            +
                weak_data = load_json(WEAK_FILE)
         
     | 
| 90 | 
         
            +
                if "phrases" not in weak_data:
         
     | 
| 91 | 
         
            +
                    weak_data["phrases"] = []
         
     | 
| 92 | 
         
            +
                if phrase_obj not in weak_data["phrases"]:
         
     | 
| 93 | 
         
            +
                    weak_data["phrases"].append(phrase_obj)
         
     | 
| 94 | 
         
            +
                    save_json(WEAK_FILE, weak_data)
         
     | 
| 95 | 
         
            +
                    return jsonify({"message": "苦手フレーズとして追加しました", "phrase": phrase_obj})
         
     | 
| 96 | 
         
            +
                else:
         
     | 
| 97 | 
         
            +
                    return jsonify({"message": "既に苦手フレーズとして登録済みです", "phrase": phrase_obj})
         
     | 
| 98 | 
         
            +
             
     | 
| 99 | 
         
            +
            @app.route("/categories", methods=["GET"])
         
     | 
| 100 | 
         
            +
            def categories():
         
     | 
| 101 | 
         
            +
                data = load_json(DATA_FILE)
         
     | 
| 102 | 
         
            +
                cats = []
         
     | 
| 103 | 
         
            +
                for category in data["phrases"]:
         
     | 
| 104 | 
         
            +
                    cats.append({
         
     | 
| 105 | 
         
            +
                        "english": category.get("category_english", ""),
         
     | 
| 106 | 
         
            +
                        "japanese": category.get("category_japanese", "")
         
     | 
| 107 | 
         
            +
                    })
         
     | 
| 108 | 
         
            +
                return jsonify(cats)
         
     | 
| 109 | 
         
            +
             
     | 
| 110 | 
         
            +
            @app.route("/")
         
     | 
| 111 | 
         
            +
            def index():
         
     | 
| 112 | 
         
            +
                return send_from_directory(".", "index.html")
         
     | 
| 113 | 
         
            +
             
     | 
| 114 | 
         
            +
            @app.route("/<path:filename>")
         
     | 
| 115 | 
         
            +
            def static_files(filename):
         
     | 
| 116 | 
         
            +
                return send_from_directory(".", filename)
         
     | 
| 117 | 
         
            +
             
     | 
| 118 | 
         
            +
            if __name__ == "__main__":
         
     | 
| 119 | 
         
            +
                # Hugging Face Spaces では PORT 環境変数が指定されるので、それを利用
         
     | 
| 120 | 
         
            +
                port = int(os.environ.get("PORT", 7860))
         
     | 
| 121 | 
         
            +
                app.run(debug=True, host="0.0.0.0", port=port)
         
     | 
    	
        requirements (1).txt
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
         | 
| 
         | 
|
| 1 | 
         
            +
            Flask
         
     |