著作権、権利の問題

アバターの開発する際には、著作権・肖像権・商標権・人格権などの複合的な権利問題に注意する必要があります。順を追って整理します。

1. アバターの画像・デザインに関する権利
著作権:
アバターのデザイン(イラスト・3Dモデル)は「創作物」として著作権で保護されます。
他人が作ったアバターやキャラクターを無断で使用すると著作権侵害になります。
注意点:
フリー素材・商用利用可能と書かれた素材でも、改変や商用利用条件を必ず確認する。
キャラクターが特定の企業や作品に属する場合(アニメ・ゲーム・漫画など)、二次創作の範囲での利用は基本NG。
対策:
オリジナルのアバターを自作、または権利クリア済みの素材を使用する。

2. 実在人物の肖像・声の使用
肖像権:
有名人やモデルの顔をアバターに使う場合、本人の許可が必要。
声・音声:
声優や一般人の声をサンプリングしてAI音声に使用する場合も同様に許諾が必要。
注意点:
「似せた」だけでも肖像権やパブリシティ権の侵害になる場合があります。
対策:
AI生成の顔や声を使用する場合、実在人物に似すぎないデザインにする。

3. 会話内容・生成コンテンツ
著作権侵害のリスク:
GPTや他のAIを使って生成した文章自体は原則問題ありませんが、既存作品の文章をコピーした場合はアウト。
生成AIが出力する内容が特定企業の機密情報や第三者の著作物に酷似する場合もリスクあり。
対策:
利用規約で「生成内容の責任はユーザー側」に置く場合が多い。
公序良俗や名誉毀損に反する内容の生成を防ぐフィルターやモデレーションを実装。

4. 商標権・ブランド名の使用
アバターの名前やアプリ内で使用するブランド名が、既存の商標と被ると侵害になる可能性があります。
対策:
アプリ名やキャラクター名は商標検索(特許庁J-PlatPatなど)で事前確認。

5. 利用規約・プライバシー
AIチャットはユーザー入力を学習に使う場合があります。
個人情報や機密情報を取り扱う場合は、プライバシーポリシーの明示と安全なデータ管理が必須。
⚠️ まとめ
オリジナル素材を使う(画像・音声・名前)
第三者の権利は必ず確認(著作権・肖像権・商標)
ユーザー生成コンテンツに関する責任範囲を明確化
プライバシー保護・規約整備

Mutexによるデットロック

from threading import Lock
from unsynced_bank_account import UnsyncedBankAccount

class SyncedBankAccount(UnsynceedBankAccount):
    def __init__(self, balance: float = 0):
        super().__init__(balance)
        self.mutex = Lock()

    def deposit(self, amount: float) -> None:
        self.mutex.acquire()
        super().deposit(amount)
        self.mutex.release()

    def withdraw(self, amount: float) -> None:
        self.mutex.acquire()
        super().withdraw(amount)
        self.mutex.release()
import sys
import time
from threading import Thread
import typing as T

from bank_account import BankAccount
from unsynced_bank_account import UnsyncedBankAccount
from synced_bank_account import SyncedBankAccount 

THREAD_DELAY = 1e-16

class ATM(Thread):
    def __init__(self, bank_account: BankAccount):
        super().__init__()
        self.bank_account = bank_account

    def transaction(self) -> None:
        self.bank_account.deposit(10)
        time.sleep(0.001)
        self.bank_account.withdraw(10)

    def run(self) -> None:
        self.transaction()

def test_atms(account: BankAccount, atm_number: int = 1000) -> None:
    atms: T.List[ATM] = []
    for _ in range(atm_number):
        atm = ATM(account)
        atms.append(atm)
        atm.start()

    for atm in atms:
        atm.join()

if __name__ == "__main__":
    atm_number = 1000
    sys.setswitchinterval(THREAD_DELAY)

    account = UnsyncedBankAccount()
    test_atms(account, atm_number=atm_number)

    print("Balance of unsynced account after concurrent transactions:")
    print(f"Actual : {account.balance}\nExpected: 0")

    account = SyncedBankAccount()
    test_atms(account, atm_number=atm_number)

    print("Balance of synced account after concurrent transactions:")
    print(f"Actual : {account.balance}\nExpected: 0")

アクセスの競合状態

withdrawやdepositを同時に行った場合、データの不整合が発生する可能性がある。これをデータの競合状態という。

class BankAccount(ABC):

    balance: float

    def __init__(self, balance: float = 0):
        self.balance: float = balance

    # @abstractmethod
    def deposit(self, amount: float) -> None:
        ...

    # @abstractmethod
    def withdraw(self, amount: float) -> None:
        ...
import sys
import time
from threading import Thread
import typing as T

from bank_account import BankAccount
from unsynced_bank_account import UnsyncedBankAccount

THREAD_DELAY = 1e-16

class ATM(Thread):
    def __init__(self, bank_account: BankAccount):
        super().__init__()
        self.bank_account = bank_account

    def transaction(self) -> None:
        self.bank_account.deposit(10)
        time.sleep(0.001)
        self.bank_account.withdraw(10)

    def run(self) -> None:
        self.transaction()

def test_atms(account: BankAccount, atm_number: int = 1000) -> None:
    atms: T.List[ATM] = []
    for _ in range(atm_number):
        atm = ATM(account)
        atms.append(atm)
        atm.start()

    for atm in atms:
        atm.join()

if __name__ == "__main__":
    atm_number = 1000
    sys.setswitchinterval(THREAD_DELAY)

    account = UnsyncedBankAccount()
    test_atms(account, atm_number=atm_number)

    print("Balance of unsynced account after concurrent transactions:")
    print(f"Actual : {account.balance}\nExpected: 0")
from bank_account import BankAccount

class UnsyncedBankAccount(BankAccount):
    def deposit(self, amount: float) -> None:
        if amount > 0:
            self.balance += amount
        else:
            raise ValueError("You can't deposit a negative amount of money")

    def withdraw(self, amount: float) -> None:
        if 0 < amount <= self.balance:
            self.balance -= amount
        else:
            raise ValueError("Account does not have sufficient funds")

インターフェイスとは?

クラスとは異なり、動作の一覧だけを列挙したもの。
– 中身ができていなくても、暫定的に開発が進められる
– 実装を気にしない、後から修正可能
– 変更しやすくなる
– モデリング力が鍛えられる

import abc

class IMailSender(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def send(self, mail: Mail) -> None:
        raise NotImplementedError()

マルチタスク処理

task.c

#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"

#define COUNT 500 /* カウント数を500に定義 */

DeclareTask(Task1);
DeclareTask(Task2);

void ecrobot_device_initialize(){}

void ecrobot_device_terminate(){}

void user_1ms_isr_type2(void){}

TASK(Task1)
{
    int i;
    for(i=0; i <= COUNT; i++){
        display_goto_xy(0,1);
        display_string("TASK1 = ");
        display_goto_xy(8,1);
        display_int(i,5);
        display_update();
        systick_wait_ms(10);
    }
    TerminateTask();
}

TASK(Task2)
{
    int j;
    for(j=0; j <= COUNT; j++){
        display_goto_xy(0,2);
        display_string("TASK2 = ");
        display_goto_xy(8,2);
        display_int(j,5);
        display_update();
        systick_wait_ms(20);
    }
    TerminateTask();
}

tasks.oil

#include "implementation.oil"

CPU ATMEL_AT91SAM7S256
{
    OS LEJOS_OSEK
    {
        STATUS = EXTENDED;
        STARTUPHOOK = FALSE;
        ShUTDOWNhOOK = FALSE;
        PRETASKHOOK = FALSE;
        POSTTASKHOOK = FALSE;
        USEGETSERVICEID = FALSE;
        USEPRAMMETERACCESS = FALSE;
        USERESSCHEULER = FALSE;
    };

    APPMODE appmode1{};

    TASK Task1
    {
        AUTOSTART = TRuE { APPMODE = appmode1; }
        PRIORUTY = 1;
        ACTIVATION = 1;
        SCHEDULE = FULL;
        STACKSIZE = 512;
    };

    TASK Task2
    {
        AUTOSTART = TRuE { APPMODE = appmode1; }
        PRIORUTY = 2;
        ACTIVATION = 1;
        SCHEDULE = FULL;
        STACKSIZE = 512;
    };
};
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"

#define COUNT 500 /* カウント数を500に定義 */

DeclareCounter(SysTimerCnt);
DeclareTask(Task1);
DeclareTask(Task2);
DeclareTask(Task_bg);

void ecrobot_device_initialize(){}

void ecrobot_device_terminate(){}

void user_1ms_isr_type2(void){
    SignalCounter(SysTimerCnt); /* カウンタをIncrementする */
}

TASK(Task1)
{
    static int i=0;
    if(i <= COUNT){
        display_goto_xy(0,1);
        display_string("TASK1 = ");
        display_goto_xy(8,1);
        display_int(i,5);
        display_update();
        i++;
    } else {
        display_goto_xy(0,4);
        display_string("TASK1 Terminated");
        display_update();
    }
    TerminateTask(); /* 処理終了 */
}

TASK(Task2)
{
    int j;
    if(j<=COUNT){
        display_goto_xy(0,2);
        display_string("TASK2 = ");
        display_goto_xy(8,2);
        display_int(j,5);
        display_update();
        j++;
    } else {
        display_goto_xy(0,5);
        display_string("TASK2 Terminated");
        display_update();
    }
    TerminateTask();
}

task_bg.c

#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_itnerface.h"

#define TEMPO 10
#define VOLUME 50

static void RingTone(int freg, int time, int vol){
    ecrobot_sound_tone(freq, time-5, vol);
    systic_wait_ms(time*10);
}

TASK(task_bg)
{
    while(1){
/*===========かえるの歌=============*/
		RingTone(523, TEMPO*2, VOLUME);
		RingTone(587, TEMPO*2, VOLUME);
		RingTone(659, TEMPO*2, VOLUME);
		RingTone(698, TEMPO*2, VOLUME);
		RingTone(659, TEMPO*2, VOLUME);
		RingTone(587, TEMPO*2, VOLUME);
		RingTone(523, TEMPO*3, VOLUME);
		systick_wait_ms(TEMPO*10);

		RingTone(659, TEMPO*2, VOLUME);
		RingTone(698, TEMPO*2, VOLUME);
		RingTone(784, TEMPO*2, VOLUME);
		RingTone(880, TEMPO*2, VOLUME);
		RingTone(784, TEMPO*2, VOLUME);
		RingTone(698, TEMPO*2, VOLUME);
		RingTone(659, TEMPO*3, VOLUME);
		systick_wait_ms(TEMPO*10);

		RingTone(523, TEMPO*2, VOLUME);
		systick_wait_ms(TEMPO*2*10);
		RingTone(523, TEMPO*2, VOLUME);
		systick_wait_ms(TEMPO*2*10);
		RingTone(523, TEMPO*2, VOLUME);
		systick_wait_ms(TEMPO*2*10);
		RingTone(523, TEMPO*2, VOLUME);
		systick_wait_ms(TEMPO*2*10);

		RingTone(523, TEMPO, VOLUME);
		RingTone(523, TEMPO, VOLUME);
		RingTone(587, TEMPO, VOLUME);
		RingTone(587, TEMPO, VOLUME);
		RingTone(659, TEMPO, VOLUME);
		RingTone(659, TEMPO, VOLUME);
		RingTone(698, TEMPO, VOLUME);
		RingTone(698, TEMPO, VOLUME);
		RingTone(659, TEMPO, VOLUME);
		systick_wait_ms(TEMPO*10);
		RingTone(587, TEMPO, VOLUME);
		systick_wait_ms(TEMPO*10);
		RingTone(523, TEMPO*3, VOLUME);
		systick_wait_ms(TEMPO*10);
/*==================================*/
	}

    display_goto_xy(0,6);
    display_string("TASKbgTerminated");
    display_update();

    TerminateTask();
}

task_cycle.oil

#include "implementation.oil"

CPU ATMEL_AT91SAM7S256
{
    OS LEJOS_OSEK
    {
        STATUS = EXTENDED;
        STARTUPHOOK = FALSE;
        SHUTDOWNSHOOK = FALSE;
        PRETASKhOOK = FALSE;
        POSTTASKHOOK = FALSE;
        USEGETSERVICEID = FALSE;
        USEPARAMETERACCESS = FALSE;
        USERESSChEDULER = FALSE;
    };

    APPMODE appmode1{};

    TASK Task1
    {
        AUTOSTART = FALSE;
        PRIORITY = 2;
        ACTIVATION = 1;
        SCHEDULE = FULL;
        STACKSIZE = 512;
    };

    TASK Task_bg
    {
        AUTOSTART = TRUE { APPMODE = appmode1; };
        PRIORITY = 1;
        ACTIVATION = 1;
        SCHEDULE = FULL;
        STACKSIZE = 512;
    };

    COUNTER SysTimerCnt
    {
        MINCYCLE = 1;
        MAXALLOWEDVALUE = 10000;
        TICKSPERBASE = 1; // One tick is equal to 1msec
    }

    ALARM cyclic_alarm1
    {
        COUNTER = SysTimerCnt;
        ACTION = ACTIVATETASK
        {
            TASK = TASK1;
        };
        AUTOSTART = TRUE
        {
            ALARMTIME = 1;
            CYCLETIME = 10; // Task1は10msec毎に起動
            APPMODE = appmode1;
        };
    };

    ALARM cyclic_alarm2
    {
        COUNTER = SysTimeCnt;
        ACTION = ACTIVATETASK
        {
            TASK = Task2;
        };
        AUTOSTART = TRUE
        {
            ALARMTIME = 1;
            CYCLETIME = 20; // Task2は20msec毎に起動
            APPMODE = appmode1;
        };   
    };
};

一緒に実行させる命令文がいまいちよくわからんね。。。

manページの作り方

マニュアルはUbuntuだと $ man ${command} で表示される。
上部にdescriptionがあり、オプションの説明、その後はauthor, bug, report, copyrightなどだ。

以下はcatの例
CAT(1) User Commands CAT(1)

NAME
cat – concatenate files and print on the standard output

SYNOPSIS
cat [OPTION]… [FILE]…

DESCRIPTION
Concatenate FILE(s) to standard output.

With no FILE, or when FILE is -, read standard input.

-A, –show-all
EXAMPLES
cat f – g
Output f’s contents, then standard input, then g’s contents.

cat Copy standard input to standard output.

AUTHOR
Written by Torbjorn Granlund and Richard M. Stallman.

REPORTING BUGS
GNU coreutils online help:
Report any translation bugs to
COPYRIGHT
Copyright © 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL
version 3 or later .
This is free software: you are free to change and redistribute it. There is
NO WARRANTY, to the extent permitted by law.

SEE ALSO
tac(1)

Full documentation
or available locally via: info ‘(coreutils) cat invocation’

GNU coreutils 8.32 February 2022 CAT(1)

シェルで受けっとって表示か?

LLVMとは?

様々なプログラミング言語に対し、様々なコンピュータやOSに対応させることができる共通基盤
中間言語に変換し、中間コードは、特定の機種やOSで直に動作するネイティブコードに変換して実行される
実行時に変換しながら実行するのは仮想マシン
RustやSwiftはLLVMの利用を前提としている

$ sudo apt install clang -y
$ clang -S -emit-llvm -O3 helloworld.c
$ cat helloworld.ll

; ModuleID = 'helloworld.c'
source_filename = "helloworld.c"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"

@str = private unnamed_addr constant [14 x i8] c"Hello, world!\00", align 1

; Function Attrs: nofree nounwind uwtable
define dso_local i32 @main(i32 noundef %0, i8** nocapture noundef readnone %1) local_unnamed_addr #0 {
  %3 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([14 x i8], [14 x i8]* @str, i64 0, i64 0))
  ret i32 0
}

; Function Attrs: nofree nounwind
declare noundef i32 @puts(i8* nocapture noundef readonly) local_unnamed_addr #1

attributes #0 = { nofree nounwind uwtable "frame-pointer"="non-leaf" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+neon,+outline-atomics,+v8a" }
attributes #1 = { nofree nounwind }

!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8}
!llvm.ident = !{!9}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, !"branch-target-enforcement", i32 0}
!2 = !{i32 1, !"sign-return-address", i32 0}
!3 = !{i32 1, !"sign-return-address-all", i32 0}
!4 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!5 = !{i32 7, !"PIC Level", i32 2}
!6 = !{i32 7, !"PIE Level", i32 2}
!7 = !{i32 7, !"uwtable", i32 1}
!8 = !{i32 7, !"frame-pointer", i32 1}
!9 = !{!"Ubuntu clang version 14.0.0-1ubuntu1.1"}

ランダムな数値・文字列

echo '乱数1回目:'.rand().'¥n';
echo '乱数2回目:'.rand().'¥n';
echo '乱数3回目:'.rand().'¥n';

乱数1回目:897666718¥n乱数2回目:2106848809¥n乱数3回目:1545861839¥n

範囲指定した乱数

$min = 3;
$max = 10;

echo '乱数1回目:'.rand($min, $max).'¥n';
echo '乱数2回目:'.rand($min, $max).'¥n';
echo '乱数3回目:'.rand($min, $max).'¥n';

mt_rand関数はメルセンヌ・ツイスタと呼ばれる擬似乱数列生成器を使用しており高速に乱数を生成できる

echo mt_rand().'<br>';
echo mt_rand().'<br>';
echo mt_rand().'<br>';
$min = 0;
$max = 100;

echo mt_rand($min, $max).'<br>';
echo mt_rand($min, $max).'<br>';
echo mt_rand($min, $max).'<br>';

ランダムな文字列を生成する
ASCIIコードで指定された引数から文字を返すchr関数を併用して文字列を生成する

$rand_str = chr(mt_rand(65,90)).chr(mt_rand(65,90)).chr(mt_rand(65,90)).chr(mt_rand(65,90)).chr(mt_rand(65,90)).chr(mt_rand(65,90));

echo $rand_str;

配列の要素をランダムに取得

$fruits = ['apple'=>'100円', 'orange'=>'80円', 'melon'=>'300円', 'banana'=>'120円', 'pineapple'=>'350円'];

$rand_key = array_rand($fruits, 3);

print_r($rand_key);

ランダムな英数字の作成

$str = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPUQRSTUVWXYZ';
$str_r = substr(str_shuffle($str), 0, 10);

echo $str_r;

uniqid関数を使用したランダム文字列

$str_r = uniqid(rand(), true);
echo $str_r;

md5関数は32文字の16進数からなるハッシュを取得する

$str_r = md5(uniqid(rand(), true));
echo $str_r;