2025年4月29日 星期二

用Python/Django/pythonanywhere實作農漁業產品交易行情



1.打開pythonanywhere建立一個mysite的Django專案,並在專案目錄下新增myapp,建立templates目錄。

2.修改mysite/settings.py

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
"""
Django settings for mysite project.

Generated by 'django-admin startproject' using Django 5.0.6.

For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-9cul&t=+y&pax8q5=)95@403s!*d&a9bp@)iq1x%)%z6%!95x-"

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['cmlin.pythonanywhere.com']


# Application definition

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "myapp",
]

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

ROOT_URLCONF = "mysite.urls"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / 'templates'],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

WSGI_APPLICATION = "mysite.wsgi.application"


# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
    }
}


# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
    },
]


# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/

LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/

STATIC_URL = "static/"

# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

# default static files settings for PythonAnywhere.
# see https://help.pythonanywhere.com/pages/DjangoStaticFiles for more info
MEDIA_ROOT = '/home/cmlin/mysite/media'
MEDIA_URL = '/media/'
STATIC_ROOT = '/home/cmlin/mysite/static'
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    BASE_DIR/'static',
    ]

2.修改urls.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
"""
URL configuration for mysite project.

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/5.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from myapp.views import index, peanut, tilapia

urlpatterns = [
    path("admin/", admin.site.urls),
    path('', index),
    path('peanut', peanut),
    path('tilapia', tilapia),
]

3.修改myapp/views.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from django.shortcuts import render
import requests
import json

# Create your views here.
def index(request):
    return render(request, "index.html", locals())

def peanut(request):
    r = requests.get('https://data.moa.gov.tw/Service/OpenData/FromM/FarmTransData.aspx')
    text = json.loads(r.text)
    rows = []
    for row in text:
        if row['作物名稱'] is None:
            continue
        if '落花生' in row['作物名稱']:
            rows.append(row)
    return render(request, "peanut.html", locals())

def tilapia(request):
    r = requests.get('https://data.moa.gov.tw/Service/OpenData/FromM/AquaticTransData.aspx')
    text = json.loads(r.text)
    rows = []
    for row in text:
        if row['魚貨名稱'] is None:
            continue
        if '吳郭魚' in row['魚貨名稱']:
            rows.append(row)
    return render(request, "tilapia.html", locals())

4.新增templates/index.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>水井井USR</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
    </head>
    <body>
        <nav class="navbar navbar-expand-sm bg-light">
            <div class="container-fluid">
                <ul class="navbar-nav">
                    <li class="nav-item">
                        <a class="nav-link" href="/peanut">落花生</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="tilapia">吳郭魚</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">Link 3</a>
                    </li>
                </ul>
            </div>
        </nav>
        <center>
            <h1>113年USR Hub:雲林沿海偏鄉的社區共好實踐計畫-以水井村三生共好為例</h1>
            <iframe width="819" height="461"
                src="https://www.youtube.com/embed/86o-pZddrjM"
                title="113年USR Hub:雲林沿海偏鄉的社區共好實踐計畫-以水井村三生共好為例"
                frameborder="0"
                allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
                referrerpolicy="strict-origin-when-cross-origin" allowfullscreen>
            </iframe>
        </center>
    </body>
</hrml>

5.新增 templates/peanut.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<html>
<head>
<TITLE>
尚虎雲產銷平台
</TITLE>
</head>
<body>
<center>
<h1>
尚虎雲產銷平台
</h1>

</center>
{% for row in rows %}
{% if forloop.first %}
<table style='width:100%' border='1'>
<caption><h2>落花生市場交易情形</h2></caption>
<tr><th>交易日期</th><th>作物代號</th><th>作物名稱</th><th>市場代碼</th><th>市場名稱</th><th>上價</th><th>中價</th><th>下價</th><th>平均價</th><th>交易量</th></tr>
{% endif %}
<tr>
<td><center>{{ row.交易日期 }}</center></td>
<td><center>{{ row.作物代號 }}</center></td>
<td><center>{{ row.作物名稱 }}</center></td>
<td><center>{{ row.市場代號 }}</center></td>
<td><center>{{ row.市場名稱 }}</center></td>
<td><center>{{ row.上價 }}</center></td>
<td><center>{{ row.中價 }}</center></td>
<td><center>{{ row.下價 }}</center></td>
<td><center>{{ row.平均價 }}</center></td>
<td><center>{{ row.交易量 }}</center></td>
</tr>
{% if forloop.last %}
</table>
{% endif %}
{% endfor %}
</body>

</html>

6.新增templates/tilapia.html



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<html>
<head>
<TITLE>
尚虎雲產銷平台
</TITLE>
</head>
<body>
<center>
<h1>
尚虎雲產銷平台
</h1>

</center>
{% for row in rows %}
{% if forloop.first %}
<table style='width:100%' border='1'>
<caption><h2>吳郭魚市場交易情形</h2></caption>
<tr><th>交易日期</th><th>品種代碼</th><th>魚貨名稱</th><th>市場名稱</th><th>上價</th><th>中價</th><th>下價</th><th>平均價</th><th>交易量</th></tr>
{% endif %}
<tr>
<td><center>{{ row.交易日期 }}</center></td>
<td><center>{{ row.品種代碼 }}</center></td>
<td><center>{{ row.魚貨名稱 }}</center></td>
<td><center>{{ row.市場名稱 }}</center></td>
<td><center>{{ row.上價 }}</center></td>
<td><center>{{ row.中價 }}</center></td>
<td><center>{{ row.下價 }}</center></td>
<td><center>{{ row.平均價 }}</center></td>
<td><center>{{ row.交易量 }}</center></td>
</tr>
{% if forloop.last %}
</table>
{% endif %}
{% endfor %}
</body>

</html>

2025年4月24日 星期四

取得今日農產品交易情形

 範例一、落花生

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import requests
import json
r = requests.get('https://data.moa.gov.tw/Service/OpenData/FromM/FarmTransData.aspx')
text = json.loads(r.text)
for row in text:
    if row['作物名稱'] is None:
        continue
    if '落花生' in row['作物名稱']:
        print ('交易日期:'+row['交易日期'])
        print ('作物名稱:'+row['作物名稱'])
        print ('市場名稱:'+row['市場名稱'])
        print ('平均價:'+str(row['平均價']))
        print ('交易量:'+str(row['交易量']))

執行結果:
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:台北一
平均價:70.0
交易量:144.0
交易日期:114.04.24
作物名稱:落花生-生
市場名稱:板橋區
平均價:35.0
交易量:150.0
交易日期:114.04.24
作物名稱:落花生-生
市場名稱:三重區
平均價:48.4
交易量:950.0
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:台中市
平均價:27.0
交易量:300.0
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:豐原區
平均價:50.0
交易量:18.0
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:高雄市
平均價:72.77
交易量:260.0
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:鳳山區
平均價:27.1
交易量:80.0
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:屏東市
平均價:20.0
交易量:100.0
交易日期:114.04.23
作物名稱:落花生-熟
市場名稱:台北二
平均價:100.0
交易量:54.0
交易日期:114.04.23
作物名稱:落花生-熟
市場名稱:台北一
平均價:70.0
交易量:134.0
交易日期:114.04.23
作物名稱:落花生-生
市場名稱:板橋區
平均價:35.0
交易量:90.0
交易日期:114.04.23
作物名稱:落花生-生
市場名稱:三重區
平均價:48.4
交易量:950.0
交易日期:114.04.23
作物名稱:落花生-生
市場名稱:台中市
平均價:30.0
交易量:3.0
交易日期:114.04.23
作物名稱:落花生-熟
市場名稱:豐原區
平均價:48.6
交易量:78.0
交易日期:114.04.23
作物名稱:落花生-熟
市場名稱:高雄市
平均價:100.0
交易量:160.0
交易日期:114.04.22
作物名稱:落花生-熟
市場名稱:台北二
平均價:100.0
交易量:60.0
交易日期:114.04.22
作物名稱:落花生-熟
市場名稱:台北一
平均價:71.2
交易量:251.0
交易日期:114.04.22
作物名稱:落花生-生
市場名稱:板橋區
平均價:31.1
交易量:450.0
交易日期:114.04.22
作物名稱:落花生-生
市場名稱:三重區
平均價:48.2
交易量:980.0
交易日期:114.04.22
作物名稱:落花生-熟
市場名稱:台中市
平均價:28.0
交易量:400.0
交易日期:114.04.22
作物名稱:落花生-熟
市場名稱:豐原區
平均價:56.8
交易量:75.2
交易日期:114.04.22
作物名稱:落花生-熟
市場名稱:高雄市
平均價:66.13
交易量:300.0
交易日期:114.04.22
作物名稱:落花生-熟
市場名稱:鳳山區
平均價:29.6
交易量:60.0
交易日期:114.04.22
作物名稱:落花生-生
市場名稱:屏東市
平均價:29.4
交易量:100.0

範例二、指定日期

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import requests
import json
r = requests.get('https://data.moa.gov.tw/Service/OpenData/FromM/FarmTransData.aspx')
text = json.loads(r.text)
for row in text:
    if row['作物名稱'] is None:
        continue
    if '落花生' in row['作物名稱'] and '114.04.24' in row['交易日期']:
        print ('交易日期:'+row['交易日期'])
        print ('作物名稱:'+row['作物名稱'])
        print ('市場名稱:'+row['市場名稱'])
        print ('平均價:'+str(row['平均價']))
        print ('交易量:'+str(row['交易量']))

執行結果:
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:台北一
平均價:70.0
交易量:144.0
交易日期:114.04.24
作物名稱:落花生-生
市場名稱:板橋區
平均價:35.0
交易量:150.0
交易日期:114.04.24
作物名稱:落花生-生
市場名稱:三重區
平均價:48.4
交易量:950.0
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:台中市
平均價:27.0
交易量:300.0
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:豐原區
平均價:50.0
交易量:18.0
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:高雄市
平均價:72.77
交易量:260.0
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:鳳山區
平均價:27.1
交易量:80.0
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:屏東市
平均價:20.0
交易量:100.0

範例三、指定市場

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import requests
import json
r = requests.get('https://data.moa.gov.tw/Service/OpenData/FromM/FarmTransData.aspx')
text = json.loads(r.text)
for row in text:
    if row['作物名稱'] is None:
        continue
    if '落花生' in row['作物名稱'] and '114.04.24' in row['交易日期'] and'台中市' in row['市場名稱'] :
        print ('交易日期:'+row['交易日期'])
        print ('作物名稱:'+row['作物名稱'])
        print ('市場名稱:'+row['市場名稱'])
        print ('平均價:'+str(row['平均價']))
        print ('交易量:'+str(row['交易量']))

執行結果:
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:台中市
平均價:27.0
交易量:300.0

範例四、多作物

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import requests
import json
r = requests.get('https://data.moa.gov.tw/Service/OpenData/FromM/FarmTransData.aspx')
crops=['落花生', '玉米-白玉米']
for crop in crops:
    text = json.loads(r.text)
    for row in text:
        if row['作物名稱'] is None:
            continue
        if '落花生' in row['作物名稱'] and '114.04.24' in row['交易日期'] and'台中市' in row['市場名稱'] :
            print ('交易日期:'+row['交易日期'])
            print ('作物名稱:'+row['作物名稱'])
            print ('市場名稱:'+row['市場名稱'])
            print ('平均價:'+str(row['平均價']))
            print ('交易量:'+str(row['交易量']))

執行結果:
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:台中市
平均價:27.0
交易量:300.0
交易日期:114.04.24
作物名稱:落花生-熟
市場名稱:台中市
平均價:27.0
交易量:300.0

2025年4月20日 星期日

[micro:bit] 亮亮鼠-多工程式

 前一篇文章:亮亮鼠

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Imports go at the top
from microbit import *
mode = 0
value = 0

def my_sound_event():
    global mode
    if microphone.current_event() == SoundEvent.LOUD:
        mode+=1
        mode%=3

run_every(my_sound_event, ms=50)

# Code in a 'while True:' loop repeats forever
microphone.set_threshold(SoundEvent.LOUD, 80)
while True:
    display.show(mode+1)
    if button_a.was_pressed():
        mode+=1
        mode%=3
    if button_b.was_pressed():
        value = 1-value
    if mode == 0:
        pin0.write_digital(value)         
    if mode == 1:
        pin0.write_digital(value)    
        value = 1-value
    if mode == 2:
        if display.read_light_level()<70:
            pin0.write_digital(1)
        else:
            pin0.write_digital(0)
    sleep(500)  

2025年4月19日 星期六

[micro:bit]亮亮鼠





Python Editor:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Imports go at the top
from microbit import *
mode = 0
value = 0

# Code in a 'while True:' loop repeats forever
microphone.set_threshold(SoundEvent.LOUD, 100)
while True:
    display.show(mode+1)
    if button_a.was_pressed():
        mode+=1
        mode%=3
    if microphone.current_event() == SoundEvent.LOUD:
        mode+=1
        mode%=3
    if button_b.was_pressed():
        value = 1-value
    if mode == 0:
        pin0.write_digital(value)         
    if mode == 1:
        pin0.write_digital(value)    
        value = 1-value
        sleep(120)
    if mode == 2:
        if display.read_light_level()<70:
            pin0.write_digital(1)
        else:
            pin0.write_digital(0)
    sleep(120)

[micro:bit]音樂盒

積木程式:


 

Python程式碼:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
mp3Player.mp3_set_serial(SerialPin.P0)
servos.P2.run(50)
mp3Player.set_volume(22)
play = 0
servos.P2.set_angle(90)
basic.pause(2000)
servos.P2.set_angle(180)
servos.P2.run(50)
mp3Player.execute(mp3Player.playType.PLAY_NEXT)

def on_forever():
    global play
    led.plot_bar_graph(input.sound_level(), 255)
    basic.pause(500)
    play = play + 1
    if play == 100:
        play = 0
        mp3Player.execute(mp3Player.playType.PLAY_NEXT)
        servos.P2.set_angle(0)
        servos.P2.run(50)
basic.forever(on_forever)

2025年4月8日 星期二

修改HUB 8735 Ultra內建範例來控制JQ 6500來播放MP3音樂

 前篇文章:國產WiFi晶片8735 Ultra初體驗


範例一、內建範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
 This sketch shows how to use GPIO interrupt and doing task in interrupt handler

 At first we light on LED.
 As button pin meets voltage rise signal, then interrupt happen and invoke interrupt handler.
 Then we change LED state.
    If LED was light on, then turn it off.
    If LED was light off, then turn it on.

 Example guide:
 https://www.amebaiot.com/en/amebapro2-arduino-gpio-interrupt/
 */

int button = PUSH_BTN;
int led = LED_BUILTIN;

int ledState = 1;

void button_handler(uint32_t id, uint32_t event)
{
    if (ledState == 0) {
        // turn on LED
        ledState = 1;
        digitalWrite(led, ledState);
    } else {
        // turn off LED
        ledState = 0;
        digitalWrite(led, ledState);
    }
}

void setup()
{
    pinMode(led, OUTPUT);
    digitalWrite(led, ledState);

    pinMode(button, INPUT_IRQ_RISE);
    digitalSetIrqHandler(button, button_handler);
}

void loop()
{
    delay(1000);
}


範例二、把LED控制接腳改成AMB_D0(PF_2 G)

接腳:

JQ6500 SPK+、SPK-接至喇叭的正負極。
JQ6500 Vcc、GND接至HUB 8735 Ultra Vcc和GND
JQ6500 K1接至PF_2

程式:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
 This sketch shows how to use GPIO interrupt and doing task in interrupt handler

 At first we light on LED.
 As button pin meets voltage rise signal, then interrupt happen and invoke interrupt handler.
 Then we change LED state.
    If LED was light on, then turn it off.
    If LED was light off, then turn it on.

 Example guide:
 https://www.amebaiot.com/en/amebapro2-arduino-gpio-interrupt/
 */

int button = PUSH_BTN;
int led = AMB_D0;

int ledState = 1;

void button_handler(uint32_t id, uint32_t event)
{
    if (ledState == 0) {
        // turn on LED
        ledState = 1;
        digitalWrite(led, ledState);
    } else {
        // turn off LED
        ledState = 0;
        digitalWrite(led, ledState);
    }
}

void setup()
{
    pinMode(led, OUTPUT);
    digitalWrite(led, ledState);

    pinMode(button, INPUT_IRQ_RISE);
    digitalSetIrqHandler(button, button_handler);
}

void loop()
{
    delay(1000);
}


傾聽作品:拍掌牛擺頭外也能啟閉鳥叫聲

上一篇文章:彩虹鳥和行動牛



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def on_button_pressed_a():
    radio.send_string("action cow")
input.on_button_pressed(Button.A, on_button_pressed_a)

def on_button_pressed_b():
    radio.send_string("rainbow bird")
input.on_button_pressed(Button.B, on_button_pressed_b)

def on_sound_loud():
    global mode
    if listen == 1:
        mode = (mode + 1) % 2
        basic.show_icon(IconNames.HEART)
        servos.P1.set_angle(60)
        basic.pause(500)
        servos.P1.set_angle(120)
        basic.pause(500)
        servos.P1.set_angle(90)
        basic.show_icon(IconNames.ANGRY)
input.on_sound(DetectedSound.LOUD, on_sound_loud)

listen = 0
mode = 0
strip = neopixel.create(DigitalPin.P2, 4, NeoPixelMode.RGB)
strip.show_rainbow(1, 360)
strip.show()
servos.P1.set_angle(90)
mode = 0
radio.set_group(88)
basic.show_icon(IconNames.ANGRY)
listen = 1
mode = 0

def on_every_interval():
    if mode == 1:
        strip.rotate(1)
        strip.show()
loops.every_interval(500, on_every_interval)

def on_forever():
    global listen
    if mode == 1:
        listen = 0
        for index in range(randint(10, 200)):
            music.play_sound_effect(music.create_sound_effect(WaveShape.SAWTOOTH,
                    randint(1, 5000),
                    randint(1, 5000),
                    randint(0, 1024),
                    randint(0, 1024),
                    randint(40, 100),
                    SoundExpressionEffect.VIBRATO,
                    InterpolationCurve.CURVE),
                SoundExpressionPlayMode.UNTIL_DONE)
        basic.pause(600)
        listen = 1
        basic.pause(randint(1000, 10000))
basic.forever(on_forever)

2025年4月7日 星期一

傾聽作品:彩虹鳥和行動牛

 


MakeCode程式:


Python程式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
def on_button_pressed_a():
    radio.send_string("action cow")
input.on_button_pressed(Button.A, on_button_pressed_a)

def on_button_pressed_b():
    radio.send_string("rainbow bird")
input.on_button_pressed(Button.B, on_button_pressed_b)

def on_sound_loud():
    global mode
    mode = (mode + 1) % 2
    basic.show_icon(IconNames.HEART)
    servos.P1.set_angle(60)
    basic.pause(500)
    servos.P1.set_angle(120)
    basic.pause(500)
    servos.P1.set_angle(90)
    basic.show_icon(IconNames.ANGRY)
input.on_sound(DetectedSound.LOUD, on_sound_loud)

mode = 0
strip = neopixel.create(DigitalPin.P2, 4, NeoPixelMode.RGB)
strip.show_rainbow(1, 360)
strip.show()
servos.P1.set_angle(90)
mode = 0
radio.set_group(88)
basic.show_icon(IconNames.ANGRY)

def on_every_interval():
    if mode == 1:
        strip.rotate(1)
        strip.show()
loops.every_interval(500, on_every_interval)

def on_forever():
    for index in range(randint(10, 200)):
        music.play_sound_effect(music.create_sound_effect(WaveShape.SAWTOOTH,
                randint(1, 5000),
                randint(1, 5000),
                randint(0, 1024),
                randint(0, 1024),
                randint(40, 100),
                SoundExpressionEffect.VIBRATO,
                InterpolationCurve.CURVE),
            SoundExpressionPlayMode.UNTIL_DONE)
    basic.pause(randint(1000, 10000))
basic.forever(on_forever)


用micro:bit實作小鳥叫聲

參考資料:Jonny’s Bird

用隨機變數取替加速器資料。


Python程式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def on_forever():
    for index in range(randint(10, 200)):
        music.play_sound_effect(music.create_sound_effect(WaveShape.SAWTOOTH,
                randint(1, 5000),
                randint(1, 5000),
                randint(0, 1024),
                randint(0, 1024),
                randint(40, 100),
                SoundExpressionEffect.VIBRATO,
                InterpolationCurve.CURVE),
            SoundExpressionPlayMode.UNTIL_DONE)
    basic.pause(randint(1000, 10000))
basic.forever(on_forever)


2025年4月6日 星期日

加入影響力因子重新計算水井USR的SROI

1.加入無謂因子(Deadweight) 的程式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class SROICalculator:
    def __init__(self):
        self.inputs = {}
        self.outcomes = {}

    def add_input(self, item, amount):
        self.inputs[item] = self.inputs.get(item, 0) + amount

    def add_outcome(self, item, amount, deadweight=0):
        adjusted_amount = amount * (1 - deadweight)
        self.outcomes[item] = self.outcomes.get(item, 0) + adjusted_amount

    def calculate_sroi(self):
        total_input = sum(self.inputs.values())
        total_outcome = sum(self.outcomes.values())
        if total_input == 0:
            return float('inf')
        return round((total_outcome - total_input) / total_input, 2)

    def summary(self):
        print("📦 成本投入:")
        for k, v in self.inputs.items():
            print(f"  - {k}: NT${v}")
        print("\n🎯 調整後效益(扣除 Deadweight):")
        for k, v in self.outcomes.items():
            print(f"  - {k}: NT${v}")
        print(f"\n💡 SROI = {self.calculate_sroi()}")

# ✅ 實例:水井村案例模擬
sroi_calc = SROICalculator()

# 📦 成本投入
sroi_calc.add_input("IoT設備與感測器", 120000)
sroi_calc.add_input("水質淨化系統", 80000)
sroi_calc.add_input("教學與培訓費用", 100000)
sroi_calc.add_input("工藝材料與推廣", 50000)

# 🎯 效益(已考量 Deadweight)
sroi_calc.add_outcome("節省水資源成本", 50000, deadweight=0.15)  # 15%
sroi_calc.add_outcome("減碳社會效益(估算)", 70000, deadweight=0.10)  # 10%
sroi_calc.add_outcome("智慧養殖提升產值", 150000, deadweight=0.25)  # 25%
sroi_calc.add_outcome("地方品牌提升與觀光收益", 60000, deadweight=0.40)  # 40%
sroi_calc.add_outcome("居民生活與文化參與提升(估算)", 30000, deadweight=0.35)  # 35%

# ⏱️ 輸出結果
sroi_calc.summary()

執行結果:
📦 成本投入:
  - IoT設備與感測器: NT$120000
  - 水質淨化系統: NT$80000
  - 教學與培訓費用: NT$100000
  - 工藝材料與推廣: NT$50000

🎯 調整後效益(扣除 Deadweight):
  - 節省水資源成本: NT$42500.0
  - 減碳社會效益(估算): NT$63000.0
  - 智慧養殖提升產值: NT$112500.0
  - 地方品牌提升與觀光收益: NT$36000.0
  - 居民生活與文化參與提升(估算): NT$19500.0

💡 SROI = -0.22

2.再加入歸因因子(Attribution)和衰減因子(Drop-off)的程式(以3年為期):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class SROICalculator:
    def __init__(self):
        self.inputs = {}
        self.outcomes = {}

    def add_input(self, item, amount):
        self.inputs[item] = self.inputs.get(item, 0) + amount

    def add_outcome(self, item, amount, deadweight=0, attribution=0, dropoff=0, years=1):
        adjusted_total = 0
        for year in range(years):
            year_factor = (1 - dropoff) ** year
            adjusted = amount * (1 - deadweight) * (1 - attribution) * year_factor
            adjusted_total += adjusted
        self.outcomes[item] = self.outcomes.get(item, 0) + adjusted_total

    def calculate_sroi(self):
        total_input = sum(self.inputs.values())
        total_outcome = sum(self.outcomes.values())
        if total_input == 0:
            return float('inf')
        return round((total_outcome - total_input) / total_input, 2)

    def summary(self):
        print("📦 成本投入:")
        for k, v in self.inputs.items():
            print(f"  - {k}: NT${v}")
        print("\n🎯 調整後效益(扣除 Deadweight、歸因、遞減):")
        for k, v in self.outcomes.items():
            print(f"  - {k}: NT${round(v, 2)}")
        print(f"\n💡 SROI = {self.calculate_sroi()}")


sroi_calc = SROICalculator()

# 📦 成本投入
sroi_calc.add_input("IoT設備與感測器", 120000)
sroi_calc.add_input("水質淨化系統", 80000)
sroi_calc.add_input("教學與培訓費用", 100000)
sroi_calc.add_input("工藝材料與推廣", 50000)

# 🎯 效益:含 Deadweight、Attribution、Drop-off、years
sroi_calc.add_outcome("節省水資源成本", 50000, deadweight=0.15, attribution=0.1, dropoff=0.05, years=3)
sroi_calc.add_outcome("減碳社會效益(估算)", 70000, deadweight=0.10, attribution=0.1, dropoff=0.05, years=3)
sroi_calc.add_outcome("智慧養殖提升產值", 150000, deadweight=0.25, attribution=0.15, dropoff=0.1, years=3)
sroi_calc.add_outcome("地方品牌提升與觀光收益", 60000, deadweight=0.4, attribution=0.2, dropoff=0.1, years=3)
sroi_calc.add_outcome("居民生活與文化參與提升(估算)", 30000, deadweight=0.35, attribution=0.15, dropoff=0.05, years=3)

# ⏱️ 輸出結果
sroi_calc.summary()

執行結果:
📦 成本投入:
  - IoT設備與感測器: NT$120000
  - 水質淨化系統: NT$80000
  - 教學與培訓費用: NT$100000
  - 工藝材料與推廣: NT$50000

🎯 調整後效益(扣除 Deadweight、歸因、遞減):
  - 節省水資源成本: NT$109108.12
  - 減碳社會效益(估算): NT$161736.75
  - 智慧養殖提升產值: NT$259143.75
  - 地方品牌提升與觀光收益: NT$78048.0
  - 居民生活與文化參與提升(估算): NT$47280.19

💡 SROI = 0.87

3.再加入移轉因子(Displacement),其程式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class SROICalculator:
    def __init__(self):
        self.inputs = {}
        self.outcomes = {}

    def add_input(self, item, amount):
        self.inputs[item] = self.inputs.get(item, 0) + amount

    def add_outcome(self, item, amount, deadweight=0, attribution=0, displacement=0, dropoff=0, years=1):
        adjusted_total = 0
        for year in range(years):
            year_factor = (1 - dropoff) ** year
            adjusted = amount * (1 - deadweight) * (1 - attribution) * (1 - displacement) * year_factor
            adjusted_total += adjusted
        self.outcomes[item] = self.outcomes.get(item, 0) + adjusted_total

    def calculate_sroi(self):
        total_input = sum(self.inputs.values())
        total_outcome = sum(self.outcomes.values())
        if total_input == 0:
            return float('inf')
        return round((total_outcome - total_input) / total_input, 2)

    def summary(self):
        print("📦 成本投入:")
        for k, v in self.inputs.items():
            print(f"  - {k}: NT${v}")
        print("\n🎯 調整後效益(扣除 Deadweight、歸因、移轉、遞減):")
        for k, v in self.outcomes.items():
            print(f"  - {k}: NT${round(v, 2)}")
        print(f"\n💡 SROI = {self.calculate_sroi()}")

sroi_calc = SROICalculator()

# 📦 成本投入
sroi_calc.add_input("IoT設備與感測器", 120000)
sroi_calc.add_input("水質淨化系統", 80000)
sroi_calc.add_input("教學與培訓費用", 100000)
sroi_calc.add_input("工藝材料與推廣", 50000)

# 🎯 效益(含 Deadweight、Attribution、Displacement、Drop-off、Years)
sroi_calc.add_outcome("節省水資源成本", 50000, deadweight=0.15, attribution=0.1, displacement=0.0, dropoff=0.05, years=3)
sroi_calc.add_outcome("減碳社會效益(估算)", 70000, deadweight=0.10, attribution=0.1, displacement=0.0, dropoff=0.05, years=3)
sroi_calc.add_outcome("智慧養殖提升產值", 150000, deadweight=0.25, attribution=0.15, displacement=0.05, dropoff=0.1, years=3)
sroi_calc.add_outcome("地方品牌提升與觀光收益", 60000, deadweight=0.4, attribution=0.2, displacement=0.3, dropoff=0.1, years=3)
sroi_calc.add_outcome("居民生活與文化參與提升", 30000, deadweight=0.35, attribution=0.15, displacement=0.0, dropoff=0.05, years=3)

# ⏱️ 輸出結果
sroi_calc.summary()

執行結果:
📦 成本投入:
  - IoT設備與感測器: NT$120000
  - 水質淨化系統: NT$80000
  - 教學與培訓費用: NT$100000
  - 工藝材料與推廣: NT$50000

🎯 調整後效益(扣除 Deadweight、歸因、移轉、遞減):
  - 節省水資源成本: NT$109108.12
  - 減碳社會效益(估算): NT$161736.75
  - 智慧養殖提升產值: NT$246186.56
  - 地方品牌提升與觀光收益: NT$54633.6
  - 居民生活與文化參與提升: NT$47280.19

💡 SROI = 0.77