芙丸箴言紀念版

贊助我 Steam 遊戲

隨機產生一組芙丸歷年來的 16 字箴言,讓粉絲們加強複習之外,更能藉此緬懷他們永遠的領袖。

四則運算版

以解答四則運算的方式讓使用者加強心算能力。

<!-- HTML Markup (index.php)-->
<form method="post">
    <img src="captcha.php?type=regular" alt="" />
    <input type="text" name="captcha" />
</form>
<php
// (captcha.php)
// 引入 Class
require('captcha.class.php');

// 建立 CAPTCHA Object
// @param {string} 字型完整路徑
$CAPTCHA = new Captcha('/var/usr/font.ttf');

$type = isset($_GET['type']) ? $_GET['type'] : null;

switch (strtolower($type)) {
    
    case 'regular':
        // 輸出圖形並產生四則運算 CAPTCHA
        // @return {string}
        $code = $CAPTCHA->regular([
            'width'    => 130, // 圖形寬度,單位 px
            'height'   => 40,  // 圖形高度,單位 px
            'fontSize' => 26,  // 字型大小,單位 px
        ]);
        $_SESSION['regular'] = $code;
        break;
    case 'chinese':
        // 輸出圖形並產生箴言 CAPTCHA
        // @return {string}
        $code = $CAPTCHA->chinese([
            'width'    => 180, // 圖形寬度,單位 px
            'height'   => 50,  // 圖形高度,單位 px
            'fontSize' => 28,  // 字型大小,單位 px
        ]);
        $_SESSION['chinese'] = $code;
        break;
}

// 比對 CAPTCHA 值
// @return {boolean} true|false
$result = $CAPTCHA->isCorrect($_SESSION['regular'], $_POST['captcha']);
$result = $CAPTCHA->isCorrect($_SESSION['chinese'], $_POST['captcha']);
// Download: http://app.essoduke.org/files/captcha.class.txt
<?php
/**
 * CAPTCHA class
 *
 * @author Essoduke Chang <essoduke@gmail.com>
 * @version 1.2
 * @link {http://app.essoduke.org/captcha}
 * @license The MIT License
 * Release 2015.03.12.153129
 */
class Captcha
{
    // Chinese dictionary pool
    private static $dictionary = [
        '務實面對', '冷靜思考', '徹底檢討', '找出解方', '事到如今', '恐需速定',
        '勿再猶豫', '嫁給我吧', '正視現實', '互不否認', '為民興利', '兩岸和平',
        '同舟共濟', '彼此扶持', '深化合作', '開創未來', '積極人生', '謙虛滿分',
        '充實自我', '關懷他人', '建立互信', '擱置爭議', '共創雙贏', '坦然面對',
        '記取教訓', '堅持改革', '大步向前', '透明坦白', '互相尊重', '求同存異',
        '平等互利', '合情合理', '釋放善意', '好事辦好', '以民為先', '精誠合作',
        '和衷共濟', '再創雙贏', '夏日炎炎', '溺水連連', '下水之前', '注意安全',
        '累積互信', '續創雙贏', '主權在我', '和平互惠', '共同開發', '勿驕勿餒',
        '團結一心', '堅持改革', '深化民主', '主動發掘', '明快處置', '配合偵辦',
        '對外說明', '國泰民安', '天佑臺灣', '鄉親相愛', '臺灣好讚', '大敵當前',
        '嚴陣以待', '料敵從寬', '禦敵從嚴', '青山綠水', '長橋臥波', '龍舟競渡',
        '共慶端午', '跨區結親', '日新又新', '截長補短', '圓圓滿滿', '爾俸爾祿',
        '民脂民膏', '公僕加薪', '加倍用心', '預防不足', '救援吃力', '安置快速',
        '重建妥適', '尊重差異', '公平正義', '推廣自治', '自主發展', '安全容許',
        '牛豬分離', '強制標示', '排除內臟', '求同存異', '兩岸和平', '講信修睦',
        '民生為先', '同心協力', '建設台灣', '風調雨順', '國泰民安', '排除障礙',
        '調整心態', '八年入T', '能快就快', '虛心傾聽', '徹底檢討', '積極改進',
        '持續檢討', '積極改進', '上緊發條', '全力以赴', '審慎評估', '絕不妥協',
        '錙銖必較', '台灣優先'
    ];

    // Font file path
    private static $fontFullPath = null;

    /**
     * Constructor
     * @param {string} $fontPath Font file path
     */
    public function __construct($fontPath = null)
    {
        if (file_exists($fontPath)) {
            self::$fontFullPath = $fontPath;
        } else {
            exit('Specified font was not found.');
        }
    }

    /**
     * Regular CAPTCHA
     * @param {string} $key Session key name
     */
    public static function regular($options = [])
    {
        // Merge the options
        $opt = array_merge([
            'width'     => 170,
            'height'    => 50,
            'fontSize'  => false,
        ], $options);

        $code = null;
        $a = rand(1, 9); //Max value of 1st digit
        $b = rand(1, 9); //Max value of 2nd digit
        $c = rand(1, 9); //Max value of 3rd digit

        $ans = 0;
        $operator = ['', ''];

        switch (rand(1, 3)) {
            case 1 :
                $operator[0] = '+';
                switch (rand(1, 3)) {
                    case 1:
                        $operator[1] = '+';
                        $ans = $a + $b + $c;
                        break;
                    case 2:
                        $operator[1] = '-';
                        $ans = $a + $b - $c;
                        break;
                    case 3:
                        $operator[1] = 'x';
                        $ans = $a + $b * $c;
                        break;
                }
                break;
            case 2 :
                $operator[0] = '-';
                switch(rand(1, 3)){
                    case 1:
                        $operator[1] = '+';
                        $ans = $a - $b + $c;
                        break;
                    case 2:
                        $operator[1] = '-';
                        $ans = $a - $b - $c;
                        break;
                    case 3:
                        $operator[1] = 'x';
                        $ans = $a - $b * $c;
                        break;
                }
                break;
            case 3 :
                $operator[0] = 'x';
                switch(rand(1, 3)){
                    case 1:
                        $operator[1] = '+';
                        $ans = $a * $b + $c;
                        break;
                    case 2:
                        $operator[1] = '-';
                        $ans = $a * $b - $c;
                        break;
                    case 3:
                        $operator[1] = 'x';
                        $ans = $a * $b * $c;
                        break;
                }
                break;
        }
        $code = $a . $operator[0] . $b . $operator[1] . $c;
        unset($a, $b, $c, $operator);

        return self::drawImage([
            'code'     => $code,
            'answer'   => $ans,
            'width'    => $opt['width'],
            'height'   => $opt['height'],
            'fontSize' => $opt['fontSize'],
        ]);
    }

    /**
     * Chinese CAPTCHA
     * @param {string} $key Session key name
     */
    public static function chinese($options = [])
    {
        // Merge the options
        $opt = array_merge([
            'width'     => 150,
            'height'    => 40,
            'fontSize'  => false,
        ], $options);

        mt_srand((double)microtime() * 1000000);

        $rand = [];
        $pool = array_unique(self::$dictionary);
        $word = $pool[array_rand($pool)];
        $len  = iconv_strlen($word, 'utf-8');
        $code = null;

        for ($i = 0; $i < $len; $i++) {
            $randVal = mt_rand(1, $len);
            if (in_array($randVal - 1, $rand)) {
                $i--;
            } else {
                $rand[] = $randVal - 1;
            }
        }
        for ($j = 0; $j < $len; $j++) {
            $code .= iconv_substr($word, $rand[$j], 1, 'utf-8');
        }

        return self::drawImage([
            'code'     => $code,
            'answer'   => $word,
            'width'    => $opt['width'],
            'height'   => $opt['height'],
            'fontSize' => $opt['fontSize'],
        ]);
    }

    /**
     * Is CAPTCHA correct?
     * @param {string} $input Value 1
     * @param {string} $storage Value 2
     * @return {boolean}
     */
    public static function isCorrect($input, $storage)
    {
        return 0 === strcasecmp(strval($storage), strval($input));
    }

    /**
     * Image generation
     * @param {Array} $options
     * @param {string} $options.code CAPTCHA code
     * @param {string} $options.answer Correct code
     * @param {number} $options.width Image width
     * @param {number} $options.height Image height
     * @param {number} $options.fontSize Font size in px
     * @return {string} Display image and return the CAPTCHA Code
     */
    private static function drawImage($options = [])
    {
        // Merge the options
        $opt = array_merge([
            'code'      => null,
            'answer'    => null,
            'width'     => 150,
            'height'    => 40
        ], $options);

        if (empty($opt['code']) || empty($opt['answer'])) {
            return false;
        }

        // Default font size is height / 2.
        $fontSize = isset($opt['fontSize']) && false !== $opt['fontSize'] ?
                    $opt['fontSize'] :
                    ($opt['height'] * 0.6);
        $image = imagecreate($opt['width'], $opt['height']);
        // Set the colours
        $backgroundColor = imagecolorallocate($image, 255, 255, 255);
        $textColor = imagecolorallocate($image, 20, 40, 100);
        $noiseColor = imagecolorallocate($image, 100, 120, 180);

        // Random dots in background
        for ($i = 0; $i < ($opt['width'] * $opt['height']) / 8; $i++) {
            imagefilledellipse(
                $image,
                mt_rand(0, $opt['width']),
                mt_rand(0, $opt['height']),
                1,
                1,
                $noiseColor
            );
        }
        // Random lines in background
        for ($i = 0; $i < ($opt['width'] * $opt['height']) / 450; $i++) {
            imageline(
                $image,
                mt_rand(0, $opt['width']),
                mt_rand(0, $opt['height']),
                mt_rand(0, $opt['width']),
                mt_rand(0, $opt['height']),
                $noiseColor
            );
        }

        // Create textbox and add */
        $textbox = imagettfbbox(
            ($fontSize * 3 / 4),
            0,
            self::$fontFullPath,
            $opt['code']
        );
        $xr = abs(max($textbox[2], $textbox[4]));
        $yr = abs(max($textbox[5], $textbox[7]));
        $x = intval(($opt['width'] - $xr) / 4);
        $y = intval(($opt['height'] + $yr) / 2);
        imagettftext(
            $image,
            $fontSize,
            0,
            $x,
            $y,
            $textColor,
            self::$fontFullPath,
            $opt['code']
        );

        // Output image
        header('Content-Type: image/jpeg');
        imagejpeg($image);
        imagedestroy($image);
        return $opt['answer'];
    }
}
//#EOF
?>