
パーツが届きました。
2.5インチのSSDです。
8GBのメモリです。
メモリを装着。
マザーボード装着。
SSD装着。
コネクタとネジを元に戻して電源ON。
動きました。
この後、Windows10のインストーラーを入れたUSBを接続してWindows10をインストール。
過去にWindows10を動かしているのでライセンス認証は不要です。
あっ・・・。
前回までの状況はこちら。
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/HokkaidoWar

パラメータを調整して、ランダムの値の範囲をもう少し大きくしました。
private const int maxRate = 50;
private const int minRate = 1;
double attack = lastAttack.Population * (double)(r.Next(minRate, maxRate) / 10.0);
double deffence = lastDeffece.Population * (double)(r.Next(minRate, maxRate) / 10.0);
戦力値0.1倍~5倍に広げました。

清水の勝利でした。
札幌の勝利100%では無くなったので、パラメータはこれで行きましょう。
当然のことながら、このままではゲームではありません。
ただ成り行きを眺めているだけなので。
次回以降、さらにゲームっぽく改造していこうと思います。
ただただ、捨てるのもったいない。
確か7年前ぐらいに購入したノートパソコン、HP Inspiron(だったと思う)がしばらく使われないまま棚の中で眠っているので、なんとか活用できないか、と考えています。
決して捨てるのめんどくさいとか思っていません。
ええ、思っていませんとも。
電源スイッチが入らなくなるまで使い倒すつもりでいます。
まず、このノートPCのスペック(うろ覚え)についてですが、
CPUは第4世代Core i
HDDの容量は500GB
メモリ4GB
ディスプレイの解像度1280×800(フルHDより少し少ない)
このスペックで確か当時3~5万円で購入したと思う。
今の価値だったら5000円以下かもしれない。
当時のOSはWindows8。しかしWindows10にアップデートした形跡があり、後々巡り巡ってUbuntuが入っています。
今のオイラはSSDの快適さを知ってしまっているため、このスペックではPC立ち上げに時間がかかっているだけでストレスになってしまっています。
というか、今の時代にメモリ4GBとは本当の意味で役立たずです。
まずは、何に使えるかを考えるよりも、使い物になるようにカスタマイズするべきでは無かろうか。
と思いました。
という訳で、分解。
ここまで書いて写真が無いのは、写真撮る前に分解してしまったからです。

本体の裏側のネジを取ると、キーボードが外れるようになるので、キーボードと基板の接続部分を外します。
HDDの場所は分かりました。
写真の左上のヤツですね。
これをSATAの2.5インチのSSDに取り替えれば換装できそうです。

HDDを外しました。
問題はメモリの場所ですね。ここからじゃ分かりません。
なので、マザーの部分も外しちゃいましょう。

いろんなケーブル(外部インターフェースとか、バッテリーやWi-Fiモジュールなどとの接続)を外して、マザーに相当する部分を外しました。
たぶん、金属の部分がヒートシンクになっていて、その裏側にCPUがあるんだと思います。
しかし、基板のどこを見てもメモリが無いなぁ。
もしかして、シルバーの金属に覆われている箇所の下だろうか?

当たりでした。

メモリはDDR3-12800Sらしい。
Amazonで調べてみると、過去に購入したことがあるやつ。
で、交換用のパーツを発注しました。
8000円ぐらいあればマシになるはず。
問題は、元通りに組み立てられるか、と言う所だね。
結構いろんなケーブル外したぞ。
サービスでプログラムを稼働させてからは安定して動作しております。

ラズパイZeroで稼働させていますが、本体を手で触っても全然熱を感じないので、省エネだし、熱で壊れることもありません。

いいね、これ。
ただ、文字が小さいので、時刻だけ大きく表示させてもいいんじゃないかなって思っています。
ということで、フォントデータを作成中です。
Array = [
[ #0
[
0x00, 0x00, 0x00, 0x80, 0xc0, 0xf0, 0xf8, 0xf8,
0xfc, 0xfe, 0x7e, 0x3e, 0x3e, 0x1f, 0x1f, 0x1f,
0x1f, 0x1f, 0x1f, 0x1f, 0x3f, 0x3e, 0x7e, 0xfe,
0xfc, 0xf8, 0xf8, 0xf0, 0xc0, 0x80, 0x00, 0x00
],
[
0x00, 0xe0, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x0f,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe0
],
[
0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff
],
[
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff
],
[
0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f
],
[
0x00, 0x00, 0x00, 0x03, 0x07, 0x1f, 0x3f, 0x3f,
0x7f, 0xfe, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfe,
0x7f, 0x3f, 0x3f, 0x1f, 0x07, 0x03, 0x00, 0x00
]
],
:
:

ちょっと大きくしすぎた感がありますが、最低限数字4文字入ればなんとかなるので、このままフォントデータのビットパターンを作成していきます。(残り6文字)
前回までの状況はこちら。
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/diet-mng
詳細画面を作成していきます。
これも体重管理の画面を流用してさくっと作成していきます。
処理部分は後で実装します。
web.php
Route::get('/eating', 'Eating\EatingController@index')->name('eating');
EatingController.php
<?php
namespace App\Http\Controllers\Eating;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class EatingController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('eating');
}
}
eating.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">食事管理</div>
<div class="panel-body">
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
</div>
<eating-list-component></eating-list-component>
</div>
</div>
</div>
</div>
@endsection
app.js
Vue.component('eating-list-component', require('./components/Eating/EatingListComponent.vue'));
EatingDashboardComponent.vue
<template>
<div>
<div class="dashboard">
<div class="chart">
<canvas id="eating"></canvas>
</div>
<div class="command">
<ul>
<li><a @click="onClickPrev">prev</a></li>
<li><a @click="onClickNext">next</a></li>
</ul>
<ul>
<li><a @click="onClickInput">クイック入力</a></li>
<li><a href="/eating">詳細</a></li>
</ul>
</div>
</div>
<eating-input-dialog-component :show="showInputDialogContent" @update="invokeUpdateList"></eating-input-dialog-component>
</div>
</template>
EatingListComponent.vue
<template>
<div>
<div>
<p id="navi">> <a href="/home">HOME</a></p>
<p id="inputbutton">
<button @click="onClickInput">データ入力</button>
</p>
<div id="pagenate">
<ul>
<li>
<a href="#" v-if="prevShow" @click="prevPage()"><</a>
<b v-else><</b>
</li>
<li v-for="page in pagenates">
<a href="#" v-if="currentPage != page" @click="changePage(page)">{{ page }}</a>
<b v-else>{{ page }}</b>
</li>
<li>
<a href="#" v-if="nextShow" @click="nextPage()">></a>
<b v-else>></b>
</li>
</ul>
</div>
<table class="eatinglist">
<tbody>
<tr>
<th class="date">日時</th>
<th class="protein">タンパク質</th>
<th class="liqid">脂質</th>
<th class="carbo">炭水化物</th>
<th class="calorie">カロリー</th>
<th class="edit"></th>
<th class="delele"></th>
</tr>
<tr v-for="data in datalists">
<td class="date">{{ data.date}}</td>
<td class="protein">{{ data.protein}}</td>
<td class="liqid">{{ data.liqid}}</td>
<td class="carbo">{{ data.carbo}}</td>
<td class="calorie">{{ data.calorie}}</td>
<td class="edit"><a @click="onClickEdit(data.id)">Edit</a></td>
<td class="delele"><a @click="onClickDelete(data.id)">Delete</a></td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
showInputDialogContent: false,
showEditDialogContent: false,
showDeleteDialogContent: false,
datalists: [],
pagenates: [],
currentPage: 1,
maxPage: 1,
param: {},
contents: {
page: "",
},
};
},
computed: {
prevShow: function() {
return this.currentPage != 1;
},
nextShow: function() {
return this.currentPage != this.maxPage;
},
},
created: function() {
},
methods: {
createPagenate: function() {
},
changePage: function(page) {
},
nextPage: function() {
},
prevPage: function() {
},
onClickInput: function() {
},
onClickEdit: function(id) {
},
onClickDelete: function(id) {
},
invokeUpdateList: function() {
},
updateList: function() {
}
}
}
</script>
app.scss
@import "eatinglist";
_eatinglist.scss
table.eatinglist {
width: 100%;
tbody tr {
th {
border: solid;
border-width: thin;
}
.date {
width: 20%;
}
.protein {
width: 15%;
}
.liqid {
width: 15%;
}
.carbo {
width: 15%;
}
.calorie {
width: 15%;
}
.edit {
width: 10%;
}
.delete {
width: 10%;
}
td {
border: solid;
border-width: thin;
text-align: right;
}
.date {
width: 20%;
}
.protein {
width: 15%;
}
.liqid {
width: 15%;
}
.carbo {
width: 15%;
}
.calorie {
width: 15%;
}
.edit {
width: 10%;
}
.delete {
width: 10%;
}
}
}
p#inputbutton {
text-align: right;
margin-right: 10px;
}
p#navi {
margin-left: 10px;
}
div#pagenate {
text-align: right;
ul li {
margin-left: 5px;
margin-right: 5px;
display: inline;
}
}

まぁ、まだデータがないからね。
今日はマジ暑くてしんどい。
Android10でGPSの位置情報を取得する方法を調べてみたところ、
まぁ、かなり古い情報しか発掘されなくて。
こういう情報はどんどん更新されていくから、バージョンが変わると調べ直すのめんどくさい。
一番有効な情報はこちらの記事でした。
https://dev.classmethod.jp/articles/android-get-location/
Javaではなく、Kotlinのコードですが、オイラの環境でも動くのを確認しました。(Pixel3)
Javaのコードが全く見つからなくて、
もう時代はKotlinで、Javaはオワコンなんですかね・・・
仕方が無い、kotlin勉強するか。
偶然、Kindle Unlimited対象の書籍が見つかったので、時間があるときに読んでいます。
時間はたっぷりあるけどな。
今後は、GPSの位置情報を使った、ちょっとしたお遊びアプリを考えています。
前回までの状況はこちら。
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/HokkaidoWar

前回は対戦相手を選択する処理を作成したので、
今回は実際にバトルを行う処理を作成します。
class Battle
{
public void NextTurn()
{
if (lastDeffece != null)
{
lastDeffece.ClearPaint();
}
if (lastAttack != null)
{
lastAttack.ClearPaint();
}
var targets = _cities[cityCnt].GetLinkedCities();
var r = Singleton.GetRandom();
int targetIdx = r.Next(0, targets.Count + 1);
lastAttack = _cities[cityCnt];
lastAttack.PaintAttackColor();
var info = Singleton.GetGameProcessInfomation();
if(targetIdx >= targets.Count)
{
info.ShowText(lastAttack.GetPosition(), string.Format("{0} turn {1} / {2} {3}",
turn, cityCnt + 1, _cities.Count, lastAttack.Name));
}
else
{
lastDeffece = targets[targetIdx];
lastDeffece.PaintDeffenceColor();
float attack = lastAttack.Population * (float)(r.Next(5, 30) / 10.0);
float deffence = lastDeffece.Population * (float)(r.Next(5, 30) / 10.0);
if(attack > deffence)
{
info.ShowText(lastAttack.GetPosition(), string.Format("{0} turn {1} / {2} {3}\r\ntarget {4} \r\n{5} vs {6}\r\nwin",
turn, cityCnt + 1, _cities.Count, lastAttack.Name, lastDeffece.Name, (int)attack, (int)deffence));
lastAttack.CombinationCity(lastDeffece);
_cities.Remove(lastDeffece);
lastDeffece = null;
}
else
{
info.ShowText(lastAttack.GetPosition(), string.Format("{0} turn {1} / {2} {3}\r\ntarget {4} \r\n{5} vs {6}\r\nlose",
turn, cityCnt + 1, _cities.Count, lastAttack.Name, lastDeffece.Name, (int)attack, (int)deffence));
}
}
cityCnt++;
if(cityCnt >= _cities.Count)
{
_cities = cityRandomReplace(_cities);
cityCnt = 0;
turn++;
}
}
class City
{
public List<Map> GetMaps()
{
return _maps;
}
public void CombinationCity(City lose)
{
addMaps(lose.GetMaps());
_population += lose.Population;
}
private void addMaps(List<Map> maps)
{
foreach(var m in maps)
{
m.SetCity(this);
}
_maps.AddRange(maps);
}
とりあえず、0.5倍~3倍の乱数で戦力値に補正をかけて勝敗を決めます。
そして、攻撃側が勝利した場合は防御側を吸収合併します。
これで一通り実装は完了したので、実際に大戦を実行しましょう。

札幌の一人勝ちでした。
もうちょっとパラメータを調整しないといけないですね。
最新ソースはこちら。
https://github.com/takishita2nd/RaspiDisplayMonitor

以前使用していた12個のスイッチは3つの信号と4つの制御線の組み合わせで検出していましたが、

いまはスイッチは1個なので、エッジの割り込みで操作できるはずです。
スレッドが一つ無くなるので、ラズパイZeroでも動作が軽くなると思います。
import RPi.GPIO as GPIO
import time
import datetime
import calendar
import GLCD
import AM2320
import Weather
sw = False
def __main__():
global sw
GPIO.setmode(GPIO.BCM)
GPIO.setup(22,GPIO.IN)
GPIO.add_event_detect(22, GPIO.FALLING, callback=callback, bouncetime=300)
GLCD.PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
GLCD.GLCDInit()
GLCD.GLCDDisplayClear()
roop = 10 * 60 * 60
mode = 1
try:
while True:
if sw == True:
GLCD.GLCDDisplayClear()
mode += 1
if mode > 3:
mode = 1
sw = False
if mode == 1:
if roop >= 10 * 60 * 60:
GLCD.GLCDDisplayClear()
Weather.RequestAPI()
weather = Weather.GetWeather()
temp = Weather.GetTemp()
roop = 0
GLCD.GLCDPuts(1, 0, "Date :")
GLCD.GLCDPuts(5, 8, datetime.datetime.now().strftime('%Y:%m:%d %A '))
GLCD.GLCDPuts(1, 16, "Weather :")
GLCD.GLCDPuts(10,24, weather)
GLCD.GLCDPuts(10,32, "Temp : " + format(temp) + 'C')
GLCD.GLCDPuts(1, 40, "Time : " + datetime.datetime.now().strftime('%H:%M'))
GLCD.GLCDPuts(1, 48, "Humidity : " + AM2320.GetHum() + '%')
GLCD.GLCDPuts(1, 56, "Temperature : " + AM2320.GetTemp() + 'C')
roop += 1
elif mode == 2:
cal = calendar.month(datetime.datetime.now().year, datetime.datetime.now().month)
cals = cal.split("\n")
y = 0
for c in cals:
GLCD.GLCDPuts(1, y, c)
y += 8
elif mode == 3:
GLCD.drowMashiro()
time.sleep(1)
except KeyboardInterrupt:
GLCD.GLCDDisplayClear()
GPIO.cleanup()
def callback(channel):
global sw
sw = True
__main__()
GPIO.add_event_detect()で割り込み処理の登録を行います。
監視するGPIOの番号、エッジ(HIGH/LOW)、コールバック関数、検出間隔指定します。
上の処理では、GPIO22が下りエッジを検出したらcallback()が実行されます。
スイッチ検出がかなりスムーズになりました。
前回までの状況はこちら。
最新ソースファイルはこちら(gitHub)
https://github.com/takishita2nd/diet-mng
入力ダイアログの画面を作成していきます。
ベースは体重管理で作成したものを使用します。
実際の処理は後で作成します。
EatingInputDialogComponent.vue
<template>
<div>
<div id="overlay" v-show="show">
<div id="content">
<p v-if="error_flg == true" class="error">
<ui>
<li v-for="error in errors">{{ error }}</li>
</ui>
</p>
<table class="edit">
<tbody>
<tr>
<td>品名</td>
<td><input type="text" v-model="contents.item" /></td>
</tr>
<tr>
<td>タンパク質</td>
<td><input type="number" v-model="contents.protein" /></td>
</tr>
<tr>
<td>脂質</td>
<td><input type="number" v-model="contents.riqid" /></td>
</tr>
<tr>
<td>炭水化物</td>
<td><input type="number" v-model="contents.carbo" /></td>
</tr>
<tr>
<td>カロリー</td>
<td><input type="number" v-model="contents.calorie" /></td>
</tr>
</tbody>
</table>
<p id="command">
<button @click="clickAdd">入力</button>
<button @click="closeModal">閉じる</button>
</p>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['show'],
data() {
return {
errors: [],
error_flg: [],
param: {},
contents: {
item: "",
protein: "",
riqid: "",
carbo: "",
calorie: "",
},
};
},
created: function() {
},
methods: {
clickAdd: function() {
},
closeModal: function() {
this.$parent.showInputDialogContent = false;
},
clear: function() {
this.contents.item = "";
this.contents.protein = "";
this.contents.riqid = "";
this.contents.carbo = "";
this.contents.calorie = "";
this.error_flg = false;
this.errors = [];
}
}
}
</script>
app.js
Vue.component('eating-input-dialog-component', require('./components/Eating/EatingInputDialogComponent.vue'));
EatingDashboardComponent.vue
<template>
<div>
<div class="dashboard">
<div class="chart">
<canvas id="eating"></canvas>
</div>
<div class="command">
<ul>
<li><a @click="onClickPrev">prev</a></li>
<li><a @click="onClickNext">next</a></li>
</ul>
<ul>
<li><a @click="onClickInput">クイック入力</a></li>
<li><a href="">詳細</a></li>
</ul>
</div>
</div>
<eating-input-dialog-component :show="showInputDialogContent" @update="invokeUpdateList"></eating-input-dialog-component>
</div>
</template>
<script>
export default {
data() {
return {
showInputDialogContent: false,
};
},
methods: {
onClickInput: function() {
this.showInputDialogContent = true;
},
invokeUpdateList: function() {
//this.graphUpdate(this.graphNum);
},
}
}
</script>

ラズパイZeroで作成したpythonプログラムをサービスに登録して、起動と同時に実行するように設定します。
以下のファイルを作成
pimonitor.service
[Unit]
Description=PIMonitor
After=syslog.target
[Service]
Type=simple
WorkingDirectory=/opt/pimonitor
ExecStart=/usr/bin/python3 main.py
TimeoutStopSec=5
StandardOutput=null
[Install]
WantedBy = multi-user.target
このファイルを/etc/systemd/system/配下にコピー
$ cp pimonitor.service /etc/systemd/system
※ /opt/pimonitor配下にソースファイル全て揃っている前提。
パーミッションの設定でrootでも実行できようにしておく
$ chmod 777 *
サービス開始
$ sudo systemctl start pimonitor.service
サービス登録
$ sudo systemctl enable pimonitor.service