「技術」カテゴリーアーカイブ

RUST勉強中、5/4の積み上げ

前回の続き。

前回作成したプログラムをテストするコードを書いていきます。

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_ok() {
        let calc = RpnCalculator::new(false);
        assert_eq!(calc.eval("5"), 5);
        assert_eq!(calc.eval("50"), 50);
        assert_eq!(calc.eval("-50"), -50);

        assert_eq!(calc.eval("2 3 +"), 5);
        assert_eq!(calc.eval("2 3 *"), 6);
        assert_eq!(calc.eval("2 3 -"), -1);
        assert_eq!(calc.eval("2 3 /"), 0);
        assert_eq!(calc.eval("2 3 %"), 2);
    }

    #[test]
    #[should_panic]
    fn test_ng() {
        let calc = RpnCalculator::new(false);
        calc.eval("1 1 ^");
    }
}

#[cfg(test)]はテストコードであることを示すアノテーション。

modはモジュールの意味。

#[test]がついた関数がテストコードとなる。

#[should_panic]をつけるとパニックを起こすことを確認するテストになる。

【デザインパターン】Strategyパターン

Strategyパターンはある条件をきっかけに中の処理を切り替えることができるパターンです。

Contextの中のStrategyを置き換えることで動作が切り替わります。

package com.example.strategy;

public interface Strategy {
	public void methodA();
	public void methodB();
}
package com.example.strategy;

public class ConcreteStrategy1 implements Strategy {

	public void methodA() {
	}

	public void methodB() {
	}

}
package com.example.strategy;

public class ConcreteStrategy2 implements Strategy{

	public void methodA() {
	}

	public void methodB() {
	}
	
}
package com.example.strategy;

public class Context {
	private Strategy strategy;
	
	public Context(Strategy strategy) {
		this.strategy = strategy;
	}

	public void methodA() {
		strategy.methodA();
	}

	public void methodB() {
		strategy.methodB();
	}
}
package com.example.strategy;

public class Main {
	public static void main(String[] args) {
		Context context1 = new Context(new ConcreteStrategy1());
		Context context2 = new Context(new ConcreteStrategy2());

		context1.methodA();
		context1.methodB();
		
		context2.methodA();
		context2.methodB();
	}
}

Pythonで画像ファイルを振り分け

画像ファイル(写真)はスマホで撮影すると、

それを自動的にoneDriveにアップロードされ、

それがPCの中に反映されるのですが、

それを年と月毎にフォルダ分けするのがめんどくさいので、

自動的に振り分けるPythonスクリプトを作成しました。

from datetime import date
import glob
import os
import pathlib
import shutil

CAMERA_ROLL = 'カメラ ロール'

class file_date:
    def __init__(self, name, year, month):
        self.name = name
        self.year = year
        self.month = month

def __main():
    folder = glob.glob(CAMERA_ROLL)
    if len(folder) != 0:
        organize_cameraroll()

def get_filelist():
    files = []
    for filename in glob.glob('*'):
        stat = os.stat(pathlib.Path(filename))
        dt = date.fromtimestamp(stat.st_ctime)
        file = file_date(filename, str(dt.year), str(dt.month).zfill(2))
        files.append(file)
    return files

def organize_cameraroll():
    os.chdir(CAMERA_ROLL)
    files = get_filelist()
    for file in files:
        if len(glob.glob(file.year)) == 0:
            os.mkdir(file.year)
        dist = file.year + "\\" +file.month
        if len(glob.glob(dist)) == 0:
            print(dist)
            os.makedirs(dist)
        if not os.path.isdir(file.name):
            pass
            shutil.move(file.name, dist + '\\' + file.name)

__main()

【デザインパターン】stateパターン

stateパターンは状態を表すクラスを導入することによって、状態に応じた処理を実行させるパターンです。

通常はif文等で状態を表す変数を評価して判断しますが、これをクラスに置き換えて処理するものです。

package com.example.state;

import java.text.SimpleDateFormat;

public interface State {
	public final static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	
	public void setState(Context context);
	public void methodA();
	public void methodB();
}
package com.example.state;

public class ConcreteState1 implements State {
	private final static State state = new ConcreteState1();

	private ConcreteState1() {
		super();
	}
	
	public static State getInstance() {
		return state;
	}
	
	public void setState(Context context) {
		int value = context.getValue();
		if(value == 1) {
			context.changeState(ConcreteState2.getInstance());
		}
	}

	public void methodA() {
		
	}

	public void methodB() {
		
	}

}
package com.example.state;

public class ConcreteState2 implements State{
	private final static State state = new ConcreteState2();
	
	private ConcreteState2() {
		super();
	}
	
	public static State getInstance() {
		return state;
	}
	
	public void setState(Context context) {
		int value = context.getValue();
		if(value == 2) {
			context.changeState(ConcreteState1.getInstance());
		}
	}

	public void methodA() {
	}

	public void methodB() {
	}
}
package com.example.state;

public class Context {
	private int value;
	private State state = ConcreteState2.getInstance();
	
	public int getValue() {
		return value;
	}
	
	public void setValue(int value) {
		this.value = value;
		state.setState(this);
	}
	
	public void changeState(State state) {
		this.state = state;
	}
	
	public void methodA() {
		state.methodA();
	}
	
	public void methodB() {
		state.methodB();
	}
}
package com.example.state;

public class Main {
	public static void main(String args[]) {
		Context context = new Context();
		
		context.setValue(1);
		context.methodA();
		context.methodB();
		context.setValue(2);
		context.methodA();
		context.methodB();
	}

}

設定した値に応じてcontextに保持するクラスのインスタンスを保持し、

その状態に応じて実行する処理を、クラスの実装で処理を変更させています。

【Linux】MySQLのrootパスワードを忘れてしまった場合の再設定方法

こちらのサイトを参考にしました。

https://www.sejuku.net/blog/83286
$ sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf

以下の記載を追加

skip-grant-tables
skip-networking

MySQL再起動

$ sudo systemctl restart mysql.service

mysqlでログインできるようになっているので、

$ mysql

パスワード再設定

ALTER USER root@localhost IDENTIFIED BY 'fugifugi';

mysqld.cnfの設定を元に戻してmysqlを再起動。

$ sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
$ sudo systemctl restart mysql.service

rootログインを確認する。

RUST勉強中、4/3の積み上げ

前回の続き。

コマンドラインで取得したファイルを読み出す処理、パラメータが無かったら標準入力から入力するコードです。

use clap::Parser;
use std::fs::File;
use std::io::{stdin, BufRead, BufReader};

#[derive(Parser, Debug)]
#[clap(
    name = "My RPM program",
    version = "1.0.0",
    author = "Your name",
    about = "Super awesome sample RPM calculator"
)]
struct Opts {
    #[clap(short, long)]
    verbose: bool,

    #[clap(name = "FILE")]
    formula_file: Option<String>,
}

fn main() {
    let opts = Opts::parse();

    if let Some(path) = opts.formula_file {
        // ファイルから読み出す
        let f = File::open(path).unwrap();
        let reader = BufReader::new(f);
        run(reader, opts.verbose);
    } else {
        // 標準入力から読み出す
        let stdin = stdin();
        let reader = stdin.lock();
        run(reader, opts.verbose);
    }
}

fn run<R: BufRead>(reader: R, verbose: bool) {
    for line in reader.lines() {
        let line = line.unwrap();
        println!("{}", line);
    }
}

Some()は変数がエラーを許容する書き方らしい。

つまりは、formula_fileに値があっても無くてもpathに挿入され、その値をif文で評価する、という作りになっている(と思う。)

unwrap()は関数の結果(Option<T>やResult<T>)からTの値を取り出す処理。

まぁ、これでも不完全の様なんだが、とりあえずここはテキストに従う。

Rust勉強中、3/27の積み上げ

この本を使用して勉強しています。

本日はコマンドラインから引数を取得する処理。

Clapを使用する方法が紹介されていたが、サンプルが古いのでそのまま使えず、結局公式のサンプルコードを見るハメに。

https://docs.rs/clap/latest/clap/

[dependencies]
clap = { version = "3.1.6", features = ["derive"] }
use clap::Parser;

#[derive(Parser, Debug)]
#[clap(
    name = "My RPM program",
    version = "1.0.0",
    author = "Your name",
    about = "Super awesome sample RPM calculator"
)]
struct Opts {
    #[clap(short, long)]
    verbose: bool,

    #[clap(name = "FILE")]
    formula_file: Option<String>,
}

fn main() {
    let opts = Opts::parse();
    match opts.formula_file {
        Some(file) => println!("File specified: {}", file),
        None => println!("No file specified."),
    }
    println!("Is verbosity specified?: {}", opts.verbose);
}

Clapを適用するには、Cargo.tomlの[dependencies]に一文を追加するだけでOK。

また、テキストではclap::Clapと書かれていたが、最新版ではclap::Parserが正解らしい。

置き換えたのはそれくらいか?

~/rust/samplecli$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/samplecli`
No file specified.
Is verbosity specified?: false

~/rust/samplecli$ cargo run -- input.txt
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/samplecli input.txt`
File specified: input.txt
Is verbosity specified?: false

~/rust/samplecli$ cargo run -- -v input.txt
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/samplecli -v input.txt`
File specified: input.txt
Is verbosity specified?: true

~/rust/samplecli$ cargo run -- -h
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/samplecli -h`
My RPM program 1.0.0
Your name
Super awesome sample RPM calculator

USAGE:
    samplecli [OPTIONS] [FILE]

ARGS:
    <FILE>    

OPTIONS:
    -h, --help       Print help information
    -v, --verbose    
    -V, --version    Print version information

~/rust/samplecli$ cargo run -- -d
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/samplecli -d`
error: Found argument '-d' which wasn't expected, or isn't valid in this context

        If you tried to supply `-d` as a value rather than a flag, use `-- -d`

USAGE:
    samplecli [OPTIONS] [FILE]

For more information try --help

~/rust/samplecli$ cargo run -- input.txt input2.txt
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/samplecli input.txt input2.txt`
error: Found argument 'input2.txt' which wasn't expected, or isn't valid in this context

USAGE:
    samplecli [OPTIONS] [FILE]

For more information try --help

MarkdownからHTMLやPDFに出力したい

Webページは通常HTMLで書かれているのですが

ITエンジニア系の人間は、情報共有のためにWikiページをMarkdownで書くことが多いです。

MarkdownはHTMLよりも簡単な構文でそれなりに見栄えのいいページを記述するためのフォーマットです。

拡張子はmd。

mdは非常に便利なのですが、

あまりにも使うケースが少ない。

そもそもmd形式のファイルを表示するためのツールが少ないと思います。

なので、もっと使い勝手のいい方法を考えてみました。

Visual Studio Codeの拡張機能をインストールします。

  • Markdown All in One
    Markdownの記述に便利なショートカットを提供するやつ
  • Markdown Preview Enhanced
    Markdownをプレビュー表示できるやつ
  • markdownlint
    Markdownの構文ミスを探して教えてくれるやつ

ctrl-k vでプレビュー表示できるので、

プレビュー表示右クリックからHTML出力できたり、PDF出力できたりします。

【自作PC】PCが可動不能になりました。

もともとの発端は、札幌市からの特別給付金が配布されたので、

これを機にPCパーツを新しいものにしたいと思い、

パーツを購入。

Ryzen 5 5600GのCPU
X570 pro4のマザーボード
RTX3050のグラボ

で、実際に組んでみてわかったことは、

  • メモリーがマザーボードに対応していない
  • ケースがマザーボードに対応していない

なので、これを解決するために札幌駅のTSUKUMOでケースとメモリーを購入。

で、それで組んでみたけどやっぱり動かない。

X570 pro4のLEDの点灯状態を見ていると、CPUとDRAMに点灯している、

でもメモリーは公式に対応しているものを刺している。

なので、CPUを今まで使用していたRyzen 5 3600に交換しました。

動きました。

これは、おそらくBIOSのバージョンが古いから、と思い、BIOSのバージョンアップ作業開始。

しかし、BIOSバージョンアップ中に固まってしまう、という現象が発生。

泣く泣く再起動してみたものの、

起動せず。

CMOSリセットとかいろいろ試してみたけど、ダメで。

昔の構成に戻してみたけど、

起動しなくなりました。

積んだ。

これが自作PCの罠か・・・

結局、パソコン工房に安いゲーミングPCを発注し、

今まで使用していたパーツに置き換えることで対処することにしました。

10万円溶けたわ。

いや、実際には10万以上かかっているけどな。

さすがにこの事態に脱力しました。

とりあえず、売れるパーツは売って資金回収しようか・・・

【デザインパターン】Observerパターン

Observerとは監視者という意味で、何らかのイベントを監視して実行させるパターンです。

package com.example.observer;

public interface Observer {
public void update(Event event);
}
package com.example.observer;

public class ConcreteObserver implements Observer {
@Override
public void update(Event event) {

}
}
package com.example.observer;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public abstract class Event {
private List<Observer> observerList = new ArrayList<>();

public void addObserver(Observer observer) {
observerList.add(observer);
}

public void deleteObserver(Observer observer) {
observerList.remove(observer);
}

public void notifyObserver() {
Iterator it = observerList.iterator();

while(it.hasNext()) {
Observer observer = (Observer)it.next();
observer.update(this);
}
}

public abstract void execute();
}
package com.example.observer;

public class ConcreteEvent extends Event {
@Override
public void execute() {
notifyObserver();
}
}
package com.example.observer;

public class Main {
public static void main(String[] args) {
Observer observer1 = new ConcreteObserver();
Observer observer2 = new ConcreteObserver();

Event event = new ConcreteEvent();
event.addObserver(observer1);
event.addObserver(observer2);

event.execute();
}
}

Observerを実装したクラスをインスタンス化してEventに追加し、後ほどEventのexecute()を実行することでupdate()の処理が実行されます。

まぁ、Observerはexecute()の処理実行を監視しているイメージです。