授業観察アプリ230223

FireHD8plusが到着したので、作業を進めてインストールしてみる。スマートフォンだと小さすぎるし10インチだと重いしで、8インチくらいがちょうど良いのかな?とりあえず1ページ目で観察者名や実験名、生徒数、インターバルなどの基本情報を入力し、2ページ目で行動を記録する、というインターフェースにしてみた。

でもこれくらい画面が広いと、
1.いっそボタンに観察対象となる行動を文字で表示する
2.座席表や簡単な作業マニュアルなどを画面上で参照可能にする
などの改善案が可能という気もする。

以下にUnity側のc#スクリプトと、サーバー側のPHPスクリプトを記載する。


1行入力やスライダーの値をPlayerPrefsに保存し、「次へ」ボタンでページ遷移するプログラム。PlayerPrefsはUnity実行環境で利用できるディスク領域のようなもの。テキストや数値などの各種パラメータを保存できる。シーンをまたぐときに使うと便利。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine.Networking;
using TMPro;


public class procP1 : MonoBehaviour
{
    public TMP_InputField input1;
    public TMP_InputField input2;
    public Slider slider1;
    public TextMeshProUGUI mes1;
    public Slider slider2;
    public TextMeshProUGUI mes2;

    // Start is called before the first frame update
    void Start()
    {
        //Screen.SetResolution(1200, 540, true, 60);    // RedmiNote11
        Screen.SetResolution(1280, 800, true, 60);      // Fire HD 8

        //read PlayerPrefs
        string username,expcode;
        int studentnum = 0;
        int interval = 0;
        username = PlayerPrefs.GetString("username", "-");
        if (username.Length > 1) {input1.text = username;}
        expcode = PlayerPrefs.GetString("expcode", "-");
        if (expcode.Length > 1) { input2.text = expcode; }
        studentnum = PlayerPrefs.GetInt("studentnum", 0);
        slider1.value = studentnum;
        interval = PlayerPrefs.GetInt("interval", 0);
        slider2.value = interval;

        /*
         username
        expcode
        studentnum
        interval
         */
    }

    // Update is called once per frame
    void Update()
    {
        mes1.text = slider1.value + "名";
        mes2.text = slider2.value + "秒";
    }

    public void procNextBtn() {

        // write playerPrefs
        PlayerPrefs.SetString("username", input1.text);
        PlayerPrefs.SetString("expcode", input2.text);
        PlayerPrefs.SetInt("studentnum", (int)slider1.value);
        PlayerPrefs.SetInt("interval", (int)slider2.value);
        SceneManager.LoadScene("P2");   // load scene "P2"
    }
}

ボタンのOn/Offを記憶し、定められた時間間隔でHTTP通信でサーバーへ値を送信するプログラム。ボタンのOn/Offは毎フレーム、文字などの更新処理は1秒間隔でおこなっている。HTTP通信はStartCoroutineで非同期処理。Post形式でサーバー側のPHPスクリプトに値を送っている。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using TMPro;
using UnityEngine.SceneManagement;
using UnityEngine.Networking;

public class procP2 : MonoBehaviour
{
    public Button b1;
    public Button b2;
    public Button b3;
    public Button b4;
    public Button b5;
    public TextMeshProUGUI mes1;
    public TextMeshProUGUI mes2;
    public TextMeshProUGUI mes3;
    public AudioClip clip1;

    bool sw1, sw2, sw3, sw4, sw5;
    Color pink;
    DateTime dt;
    long t1, t0;
    AudioSource audio;
    int interval =10;
    int currentst = 0;


    // Start is called before the first frame update
    void Start()
    {
        sw1 = sw2=sw3=sw4=sw5=false;
        pink= new Color(255f / 255f, 100f / 255f, 100f / 255f, 1f);

        // read PlayerPrefs
        interval= PlayerPrefs.GetInt("interval", 0);

        audio = gameObject.GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void Update()
    {
        dt = DateTime.Now;  // get time info

        // process SW color
        if (sw1) { b1.image.color = pink; } else { b1.image.color = Color.white; }
        if (sw2) { b2.image.color = pink; } else { b2.image.color = Color.white; }
        if (sw3) { b3.image.color = pink; } else { b3.image.color = Color.white; }
        if (sw4) { b4.image.color = pink; } else { b4.image.color = Color.white; }
        if (sw5) { b5.image.color = pink; } else { b5.image.color = Color.white; }

        ////// 1S loop //////
        t0 = t1;
        t1=(long)Time.time;
        if (t1 != t0) {
            Debug.Log(t1);
            mes2.text = "日時:" + dt;
            mes1.text = "評価者:" + PlayerPrefs.GetString("username", "-");
            mes1.text += " 研究区分:" + PlayerPrefs.GetString("expcode", "-");
            mes1.text += " 観察生徒:" + currentst + "/" + PlayerPrefs.GetInt("studentnum", 0);

            // exec HTTP communication
            if (dt.Second % interval == 0) {
                Debug.Log("HTTP_send");
                audio.PlayOneShot(clip1);
                StartCoroutine("HTTP_Post");
                sw1 = sw2 = sw3 = sw4 = sw5= false; // reset SW
                currentst++;                        // increment student cnt
            }
        }
    }

    public void ApplicationQuit()
    {
        Application.Quit();
    }

    public void procButton(int swnum)
    {
        if (swnum == 1) { sw1 = !sw1; }
        if (swnum == 2) { sw2 = !sw2; }
        if (swnum == 3) { sw3 = !sw3; }
        if (swnum == 4) { sw4 = !sw4; }
        if (swnum == 5) { sw5 = !sw5; }
    }

    IEnumerator HTTP_Post()
    {
        string URL = "http://kodamalab.sakura.ne.jp/WGL/SCRIPT/class/regist.php";
        Debug.Log("URL:" + URL);

        WWWForm form = new WWWForm();
        form.AddField("sampletime", dt.ToString());
        form.AddField("username", PlayerPrefs.GetString("username", "---"));
        form.AddField("expcode", PlayerPrefs.GetString("expcode", "---"));
        form.AddField("studentnum", PlayerPrefs.GetInt("studentnum", 99));
        form.AddField("interval", PlayerPrefs.GetInt("interval", 99));
        form.AddField("currentst", currentst);
        form.AddField("sw1", Convert.ToInt32(sw1));
        form.AddField("sw2", Convert.ToInt32(sw2));
        form.AddField("sw3", Convert.ToInt32(sw3));
        form.AddField("sw4", Convert.ToInt32(sw4));
        form.AddField("sw5", Convert.ToInt32(sw5));

        UnityWebRequest www = UnityWebRequest.Post(URL, form);
        yield return www.SendWebRequest();

        if (www.isNetworkError || www.isHttpError)
        {
            Debug.Log(www.error);
        }
        else
        {
            string log;
            log = www.downloadHandler.text;
            Debug.Log("POST process complete!:" + log);
            mes3.text = "LOG:" + log;
        }

    }
}

PHP側のスクリプト。postで受け取った値をディスクに追加方式で書き込むだけ。

<?
$stamp=strftime("%Y%m%d_%H%M%S");
$fn=strftime("./data/classdat%Y%m%d.csv");
echo"posted ";


if($_POST['username']!=""){
		
	$fp=fopen($fn,"a");
	fprintf($fp,"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
		$_POST['sampletime'],
		$_POST['username'],
		$_POST['expcode'],
		$_POST['studentnum'],
		$_POST['interval'],
		$_POST['currentst'],
		$_POST['sw1'],
		$_POST['sw2'],
		$_POST['sw3'],
		$_POST['sw4'],
		$_POST['sw5'],
		);
	fclose($fp);
	echo"->saved $fn/$stamp";

}

//echo"{$_POST['IF1']}/{$_POST['IF2']}/{$_POST['IF3']}/";
?>

コメントを残す