Quantcast
Channel: 黑暗執行緒
Viewing all 2433 articles
Browse latest View live

好用的Office萬用字元取代

$
0
0

同事出的考題,Word畫的座位表想轉成Excel,其中用到1-1,2-2格式的標示,直接複製貼上Excel,1-1、2-2會被解讀成1月1日、2月2日…

爬文找到一些Excel端解法,多要靠資料匯入克服,但座位表格子呈不規則分佈(你知道的,關主管的籠子Partition會比關部屬的大一些,大型猛獸還會有獨立獸籠高階主管還會有獨立辦公室… XD),加上想保留原有底色格線,轉格式再匯入的做法不太可行。

我想到的解法是將1-1置換成[1-1],標示效果不變而可避開Excel日期轉換。原以為要寫VBA,沒想到Word內建的萬用字元取代功能就可以搞定!

如以上展示,利用萬用字元表示法尋找"(?)-(?)"置換成"[\1-\2]",即可將"1-1"置換成"[1-1]","1-2"取代成"[1-2]"。再進一步研究,我發現Office的萬用字元可不只*, ?這麼簡單,還支援[A-Z]、[0-9]{1,3}等表示法,也有群組概念,已具備基本Regular Expression比對及取代功能,說自己只是「萬用字元」實在太謙虛 XD,但想想Word/Excel冒出「正則表示式」應該會讓很多祕書美眉皺眉頭,還是「萬用字元」吧!

摘錄Office萬用字元支援符號備查:(參考來源

尋找

類型

範例

任何單一字元

?

s?t 會找到 sat 和 set。

任何字元字串

*

s*d 會找到 sad 和 started。

文字的開頭

<

<(inter) 會找到 interesting 和 intercept,但不會找出 splintered。

文字的結尾

>

(in)> 會找到 in 和 within,但不會找出 interesting。

其中一個指定字元

[ ]

w[io]n 會找到 win 和 won。

此範圍內的任何單一字元

[-]

[r-t]ight 會找到 right 和 sight。 範圍必須依遞增順序排列。

角括弧內範圍之字元外的任何單一字元

[!x-z]

t[!a-m]ck 會找到 tock 和 tuck,但不會找出 tack 或 tick。

前一個字元或運算式正好 n 個出現處

{n}

fe{2}d 會找到 feed,但不會找出 fed。

前一個字元或運算式至少 n 個出現處

{n,}

fe{1,}d 會找到 fed 和 feed。

前一個字元或運算式 n 到 m 個出現處

{n,m}

10{1,3} 會找到 10、100 和 1000。

前一個字元或運算式一或多個出現處

@

lo@t 會找到 lot 和 loot。

又到呼口號時間:Office好威啊!


NG筆記20-Isolated Scope偵察技巧

$
0
0

很多Directive會用相同模版對應不同資料產生多個DOM元素,為確保各元素的ViewModel彼此獨立不相互干擾,需要為每筆資料建立一個Isolated Scope。最常見的例子是ng-repeat,例如:

<li ng-repeat="item in collection">
  {{item.prop}}
</li>

當ng-repeat為collection陣列產生成多個<li>,每個<li>都有一個獨立Scope,每個Scope有個item資料物件屬性,對應到collection陣列的每個元素。

像ng-repeat這類常用Directive,其Isolated Scope結構較單純且文件範例完整,並不難掌握,但對於一些複雜的第三方Directive,由於技術文章及相關教學不如官方Directive完整,常會有搞不清楚Isolated Scope有何屬性無從用起的困惑。面對此種困境,除了「Use the source, Luke!」,使用F12開發工具線上偵察也是一種解法。但如何與咻一聲滑進中斷點與Isolated Scope巧遇則是一項考驗,在此分享我常用的偵察技巧。

ui-grid為例: demo

cellTemplate的"{{row.entity.score|number}}"意味每一列資料的Isolated Scope裡有個row屬性,不難猜出row.entity對應的是myData陣列的逐筆元素。但,要如何偵察row元素的完整屬性呢?

方法1:自製debug Filter

我習慣在module裡加入一個中斷點專用Filter,寫法很簡單:

app.filter("debug", function() { return function(value) { debugger; }; });

只要將它串在待偵察物件或屬性後方(例如:{{row|debug}}),一執行到該Filter debugger便會觸發中斷(但留意在Dirty Check機制下,它被呼叫的頻率或許比你想像的高很多),我們就能用F12開發工具仔細調查傳入資料物件的底細。如下圖所示,中斷時在Console面板輸入value可互動檢視row物件的即時資訊。

方法2:angular.element().scope()

debug Filter應用時必須串接在Scope特定屬性之後,Filter接收value參數後只能由該屬性向下層展開,無法一窺Isolated Scope全貌。面對此種需求,我慣用的解法是透過jQuery選取Isolated Scope對應的元素,再以.scope()取得所屬Scope物件。

如以下範例,先設法用選擇器找到65,535所在<div>,scope()可傳回該列對應的Isolated Scope,透過Console檢視內容,我們可以看到$index、$even等ng-repeat也具備的特殊屬性,而有個col會指向該欄對應的欄位設定,至於前面提到的row屬性來自繼承,則藏在__proto__裡,用for (var p in scope)技巧列出scope所有繼承及自身屬性,我們也能把它挖出來。

利用上述兩則小技巧,下回再遇到難以捉摸的Isolated Scope也不用煩惱囉~

 

[NG系列]

http://www.darkthread.net/kolab/labs/default.aspx?m=post&t=angularjs

2014台北富邦馬拉松

$
0
0

第20馬,台北富邦馬拉松。

隨著天氣愈來愈冷,練跑漸入佳境,五公里稍催油門就有25分出頭的成績,幾回21K LSD時間都在2小時左右,甚至有Sub 2的記錄,維持520或530 Pace不若以往吃力,自我感覺十分良好,感覺狀況已攀上幾年未有過的巔峰。今年的富邦馬天氣預測15度陰天微雨,賽道平坦好跑,路協專業選手級補給不需流連(跟田中、星光、葡萄、櫻花馬的饕客級補給相比 XD)可以專心跑,加上有肯亞菁英選手領跑(謎之聲:喂!有領跑員跑在20公里之前的嗎?),天時地利人和,不破PB無顏見江東父老!(其實並沒有人在乎~)

富邦馬有北市府協辦果然很威,捷運提早到5:20發車,省去張羅交通的麻煩。早上騎著U-bike晃到動物園搭車,沒趕上5:20首班但車站空盪盪,時間還早,慢慢來無妨。

文湖線轉信義線,捷運上已見紅包包大軍集結。六點不到抵達會場,寄物完四處亂逛兼暖身,驚見流動廁所築成的長城,好不壯觀!在廁所區見到幾位「領跑員」,想到我賽前尿尿的時機抓得跟世界一流好手相同,不禁佩服起自己的專業(誤),跟領跑員們寒喧了兩句,順便討論今天的配速戰略,今天要好好幫我配速哦!(謎:我呸!)

7:00準時鳴槍起跑,15度陰天無雨,極佳的跑馬天氣。

 

過了建國南路人流較鬆,開始催油門,前25K有如神助,一度飆破5分速。中山北路馬偕醫院附近有支紅燈照相桿,對著路跑大軍狂閃,見狀我還開心地比YA,但後來有些後悔,擔心警察查號碼布寄罰單給我(誤) XD

從中山北路轉進河濱公園沒多久,我超越了4小時配速列車,之後便一路跑在4H集團前方,但有過前次的天真經驗,倒未一頭熱幻想自己就要攀上SUB 4,路還長得很,走著瞧吧~

前25K的速度如下:

01 - 05K  6:20 / 5:20 / 5:25 / 5:06 / 5:15
06 - 10K  5:09 / 4:51 / 5:10 / 5:11 / 5:04  10K 56:39 
11 – 15K  5:24 / 5:15 / 5:21 / 5:17 / 5:10
16 – 20K  5:42 / 5:23 / 5:17 / 5:11 / 5:28  20K 1:51:05
20 – 25K  5:56 / 5:24 / 5:26 / 5:54 / 5:40

速度沒有一年多前的國道馬來得快,但心率明顯低上許多,跑來並不喘,嚴格來說,狀況比上回更好~ 但馬拉松有條不變定律「只有累積,沒有奇蹟」,實力不到位,不用等待奇蹟。25K左右,右大腿外側上段出現緊繃感伴隨輕微疼痛,類似抽筋前兆但雖距抽筋臨界點仍有距離,只是疼痛一纏身,大勢已去,速度開始下滑…

26K左右,SUB4列車駛過身旁,列車長上前查票:「大叔,你的車票呢?」
掏出車票,帥氣的自強號列車長看了一眼。「你這張車票只能坐莒光號哦!要搭後面那一班」
語畢,我就被趕下車,含淚目送SUB4列車駛去… (下圖遠方的兩顆白汽球)

26 – 30K  6:30 / 5:33 / 5:53 / 6:11 / 5:49 30K 2:53:16 
31 - 35K  7:29 / 5:54 / 7:10 / 6:09 / 5:34
36 - 40K  7:48 / 7:51 / 7:29 / 7:37 / 8:07 
41 – 43K  6:20 / 6:09 / 5:16 / 4:46

自知SUB4無望,目標下修成穩穩破PB就好,前面狀況不錯存了積蓄,大約有20-30分鐘可以揮霍,原本前面不敢停下拍照,不敢多吃餅乾香蕉,這下全來,從選手模式切成觀光客模式的感覺真好~

 

最後12K開始走走跑跑,一派輕鬆地吃起先前存的老本,把目標訂在420以前完賽~

出水門回到市區,撞見壯觀的回收車隊,今天篤定不致落馬了,好想對公車吐舌頭說「啦啦啦,抓不到!抓不到!」(很幼稚呀~ orz)

基隆路地下道直到終點的倒數1K彷彿星光大道! 兩側滿滿的照相機快門不斷,讓人不敢怠慢,生怕跑不動的頽廢無神模樣貼上網被江湖人士恥笑,拿出吃奶的力氣衝呀(還得保留微笑,強顏歡笑真是人生必備技能),意外又快了幾分鐘,最後以4:17:34破了高掛一年九個月的PB!

領完獎牌浴巾便當伴手禮,天空開始飄雨。運氣不錯,跑完了才開始下,沒淋到雨,趕緊趕去坐捷運。帶著兩條鐵掉的大腿,行動遲緩,一進捷運站入口看見長長的樓梯不禁嘆了一口氣…

照慣例記錄戰利品:

獎牌一面入手!

      

【茶包射手日記】web.config修改未發生作用

$
0
0

接獲同事報案,部署至測試主機的MVC網站所有存取都出現HTTP 500錯誤:

直覺啟動偵錯SOP,先用瀏覽器測試下載靜態檔案(例如:/Content/style.css),也得到HTTP 500,判斷整個Web Application都停止運作。為查看完整訊息,在web.config中加入<customErrors mode="Off" />,但遠端瀏覽錯誤訊息未變。Terminal Service連上測試機,改用本機IE用localhost連上同一網站,沒想到仍看到如上訊息畫面[謎團!],刻意錯打<customErrorsXXX …>,訊息仍相同,將整個資料夾清空,訊息還是一樣,這就神奇了~

深呼吸,福至心靈想到權限問題,檢查網站資料夾權限,果然只設給SYSTEM、Adminstrators,未加上AppPool執行身分讀取權限。補上EVERYONE權限後再測試網站便正常了。(補充:較嚴謹做法應只授權給IIS 7.5虛擬帳戶,詳細做法可參考保哥的文章

由於權限不,IIS讀不到web.config,故加上<customErrors>及錯打<customErrorsXXX>都不生作用,倒也合理。但事後整理除錯記錄,卻發現網站資料夾缺乏權限時,本機看到的應是如下訊息:(包含非常明確確的權限不足提示,而所第一張擷圖的HTTP 500)

重新載入一次則變成另一個訊息:(也包含存取被拒提示)

二者都能明確看出權限問題。為何先前在本機看到HTTP 500畫面成了謎團,推測可能IIS或ASP.NET遭受某種神祕力量干擾,導致表現失常,因後續做過IISRESET,無法重現問題,當時也沒多想擷圖為證… 只能先歸入X檔案。

網站發生System.Net.Http簽章無法驗證錯誤

$
0
0

在一台Windows 2008R2主機部署ASP.NET MVC網站,出現System.Net.Http.dll組件簽章無法驗證的訊息,難道組件被人篡改?好巧不巧MVC程式來自第三方,莫非我要被木馬屠城了,嚇到我滴了兩滴… 冷汗。

Could not load file or assembly 'System.Net.Http' or one of its dependencies. Strong name signature could not be verified.  The assembly may have been tampered with, or it was delay signed but not fully signed with the correct private key. (Exception from HRESULT: 0x80131045)

無法載入檔案或組件 'Sytem.Net.Http' 或其相依性的其中之一。強式名稱簽章無法驗證。該組件可能已遭他人修改,或者為延遲簽署,但是未使用正確的私密金鑰完整簽署。

爬文後才知這是主機沒安裝.NET 4.5的症狀(這訊息也太迂迴了吧?),加上確認MVC網站規格是.NET 4.5無誤,檔案隱藏惡意程式警報解除,專心朝.NET版本問題偵辦。

由於.NET 4.5算是.NET 4.0的升級,故無法由資料夾判別。參考MSDN文件(如何:判斷安裝的 .NET Framework 版本)檢查Registry,沒看到Release DWORD,驗證機器尚未安裝.NET 4.5。

網站下載.NET 4.5.2,安裝後重新檢查Registry:

Release機碼出現,值為379893,驗證.NET 4.5.2版安裝成功,原本的System.Net.Http簽章錯誤就此消失,狀況解除。

Parallel.For翻船事件剖析-使用Concurrency Visualizer

$
0
0

網友Loops留言分享了一段程式:使用Parallel.For進行平行運算,原本測試平行運算速度勝過循序運算,卻迴圈加入一行Console.WriteLine("{0}", index)後情勢逆轉,跑得比循序迴圈還慢!

直覺推測此一現象肇因於Console為共用資源,多執行緒同時存取時涉及資源鎖定、協調同步、Context Switch等運作機制,衍生額外計算及IO。當平行處理邏輯複雜度不高,這些額外成本抵消掉平行處理的效益,甚至弊大於利,最終導致執行效率比循序處理還差。這點在用.NET展現多核威力(1) - 從ThreadPool翻船談起 一文曾印證過。

我將Loops的程式簡化,抽掉數學運算,只保留Console.WriteLine,簡化以便驗證Parallel.For執行15,000次Console.WriteLine()比直接跑For迴圈來得慢。在我的i7 2600執行約為870ms vs 620ms,慢了40%左右。

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Collections.Concurrent;
 
namespace TPL
{
publicclass Program
    {
static List<string> Results = new List<string>();
publicstaticvoid Main(string[] args)
        {
            RunTest(false);
            Console.WriteLine("Result:");
foreach (var s in Results)
            {
                Console.WriteLine(s);
            }
        }
 
staticvoid RunTest(bool parallel)
        {
int totalNum = 15000;
            Stopwatch timer = new Stopwatch();
            timer.Reset();
            timer.Start();
 
if (parallel)
            {
                Parallel.For(0, totalNum,
                    (i, state) =>
                    {
                        Console.WriteLine("{0}", i);
                    });
            }
else
            {
for (int i = 0; i < totalNum; i++)
                {
                    Console.WriteLine("{0}", i);
                }
            }
            timer.Stop();
            Results.Add(string.Format(
"TEST Parallel: {1}, Duration = {0:N0}ms",
                timer.ElapsedMilliseconds,
                parallel ? "Y" : "N"));
        }
    }
}

這又是一起「Parallel.For(多執行緒)陰溝翻船」事件,不難猜想與Context Switch、Lock、Wait等機制有關。但是,面對多執行緒的疑難雜症,難道我們永遠只能靠想像、揣模、猜想求解,無法「讓數據說話」、「有圖有真相」嗎?

這回我發現一個好工具-Concurrency Visualizer,專門為平行作業程式提供類似Visual Studio效能分析工具的監測及分析功能,是偵察多執行緒效能議題的神兵利器!

透過Visual Studio下載安裝:

之後Analyze選單會多出一個Concurrency Visualizer項目:

Concurrency Visualizer的運作原理與Visual Studio效能分析工具相似:啟動.NET程式後,依固定時間間隔取樣,記錄當下正在執行的程式碼位置。程式結束後統計結果,出現次數愈多,代表該部分執行較耗時,多半就是瓶頸所在。而Concurrency Visualizer被設計用來偵察多工作業程式,能提供從Thread、CPU Core角度蒐集的資訊,以利剖析多執行緒程式效能問題。

我使用Start with Current Project選項執行前述的TPL測試專案,分別RunTest(true)及RunTest(false)測試Parallel.For及單純For迴圈。由分析報告可明顯看出二者的CPU使用率差異,對Parallel.For效能較差的原因,也有了較明確的推論依據。

先看For的CPU使用狀況,850ms左右的執行時間,只有一個CLR Worker Thread,且幾乎都是Logical Core 1一核獨忙:(開啟Concurrency Visualizer側錄取會影響效能,執行時間比原先的620ms久)


Parallel.For有八個System.Threading.Tasks,產生八條CLR Worker Thread,充分利用i7的八個邏輯處理器,八核齊揚,但時間卻得花上1.4秒:

來看時間花在哪裡?

For的主要時間花在System.IO._ConsoleStream.Write(),即Console.WriteLine()實做的輸出邏輯。

Paralellel.For也有System.IO._ConsoleStream.Write()(下方藍底列)但不是最吃重的部分,最吃重的部分在SyncTextWriter.WriteLine的JITutil_MonContention/AwareLock::Contention,由Contention(競爭、衝突)字眼可理解這部分是為調解多條Thread爭用WriteLine()衝突產生的額外邏輯。由此可證,在多執行緒環境密集呼叫Console.WriteLine(),必須付出相當代價,這項觀察是解釋「Parallel.For加上Console.WriteLine()後結果逆轉」的主要證據!

最後,CPU花了近1/3時間用在Synchronization(同步處理),我們也檢視一下For與Parallel.For的不同:

For的同步很單純,只有一SwapContext,花了869ms,等於整個執行階段的時間長度,應該是Process開始、結束引發的Thread切換。

Parallel.For花在同步的時間明顯多出許多,高達5秒以上(各Thread耗用時間的總和),其中SwapContext花了2.5秒,KeRemoveQueueEx也花了2.46秒,印證增加Thread數的Context Switch成本。

Context Switch成本及資源競爭副作用是多工作業的老議題,藉由Concurrency Visualizer,我們得以一窺多執行緒運作的奧祕,對相關議題也有了新的詮釋!所以呢,你知道的…

又到了呼口號時間:Concurrency Visualizer好強哦!Visual Studio好威呀!

自製jQuery waitFor函式:等待條件成立執行作業

$
0
0

在寫JavaScript程式時,常有協調非同步作業的需求,像是作業B必須等待作業A完成後再進行,傳統做法多使用Callback函式,例如:

function doJobA(callback) {
//do something
  callback();
}
function doJobB() {
//do another thing
}
doJobA(doJobB);

學會jQuery.Deferred後,我幾乎都改用Deferred處理非同步作業,不管串接多個作業循序執行[參考]或等待多項作業完成再進行,用Deferred都不難搞定。但有一些例外情況:等待對象不在我們掌握範圍(例如:位於其他Frame、由3rd Party程式控制),或是在完成時加入Callback呼叫的修改工程浩大,我多會選擇另一條捷徑-輪詢(Polling)大法!使用setInterval每隔一小段時間(例如:0.05秒)檢查前置作業是否完成,一發現完成就觸發後續作業。走捷徑要付點代價,輪詢法有兩項缺點:1) 即時性較差,前置作業完成後要等到下次檢查才觸發後續作業,最糟會延遲一次輪詢的時間間隔 2) 前置作業完成前的反覆檢查需消耗CPU資源(故要切記,檢查邏輯愈簡單愈好,例如複雜的jQuerySelector或AJAX查詢就不是好選擇)。雖然有這些缺點,但輪詢法很單純直覺,且能用在所有非同步作業上,在我心中就像散彈槍一樣好用,不管叢林裡有什麼妖魔鬼怪,不需費心瞄準,轟一聲,問題就解決了。 XD

因為三不五時拿出來打怪,索性寫成共用函式-jQuery.waitFor()方法。基於應用彈性,我設計了兩個參數:等待時限(timeout)以及輪詢間隔(checkInterval)。timeout用來停損,避免前置作業故障時還一直輪詢到海枯石爛;checkInterval則用來控制檢查頻率,間隔愈短即時性愈高,但愈消耗CPU,可視需求自行拿捏。寫非同步程式我已經離不開jQuery Deferred,所以jQuery.waitFor()骨子裡還是用jQuery Deferred實做,傳回的是Promise物件,接上done()指定後續作業,fail()則用來處理等待逾時。完整程式及應用範例如下:demo

<!DOCTYPEhtml>
<html>
<head>
<metacharset="utf-8">
<title>waitFor函式</title>
</head>
<body>
<inputtype="button"id="b1"value="Start (5000ms)"/>
<inputtype="button"id="b2"value="Start (1000ms)"/>
<hr/>
<inputtype="button"id="trg"value="Trigger"/>
<hr/>
<ulid="display"></ul>
<scriptsrc="//code.jquery.com/jquery-2.1.1.min.js"></script>
<script>
/**
 * 條件成立時才執行
 *
 * @param check 檢查函式
 * @param timeout 最長等待時間
 * @param checkInterval 檢查間隔
 */
jQuery.waitFor = function(check, timeout, checkInterval) {
var dfd = jQuery.Deferred();
var checkHandle = setInterval(function () {
if (check()) {
      clearInterval(checkHandle);
      dfd.resolve();
    }
  }, checkInterval || 50);
var timeoutHandle = setTimeout(function () {
if (dfd.state() == "pending") {
      clearInterval(checkHandle);
      clearTimeout(timeoutHandle);
      dfd.reject();
    }
  }, timeout || 5000);
return dfd.promise();
} 
 
//測試程式
var $disp = $("#display");
function log(msg) {
var t = JSON.stringify(new Date()).split('T')[1].substr(0, 12);
  $disp.append("<li>" + t + " " + msg + "</li>")
}
var state = false;
function init() {
  state = false;
  log("Start");
}
function trigger() {
  state = true;
  log("Trigger");
}
$("#b1").click(function() {
  init();
  $.waitFor(function() { return state; }, 5000)
  .done(function() { log("Executed"); }).fail(function() { log("Timeout"); });
});
$("#b2").click(function() {
  init();
  $.waitFor(function() { return state; }, 1000)
  .done(function() { log("Executed"); }).fail(function() { log("Timeout"); });
});
$("#trg").click(trigger);
</script>
</body>
</html>

以下為操作示範。每次測試時會先將state變數設為false,接著呼叫我們自訂的jQuery.waitFor(fuction() { return state; }),每隔50ms檢查一次state,當state為true就觸發done()邏輯,若超過1秒或5秒state都還是false,則判定逾時觸發fail()邏輯,而「Trigger」按鈕則用來將state變數設為true。在測試中,先測Timeout,按鈕後什麼都不做,在5秒及1秒後會出現Timeout訊息;第二回合則驗證一按下「Trigger」鈕,done()立即執行。

以上就是我的散彈槍製作手冊,祝大家打怪順利~ XD

2014塗鴉牆回顧

$
0
0

2011新年玩過噗浪河道回顧的遊戲,這幾年生活瑣事碎碎唸的疏洪道漸漸轉到臉書,而臉書跟噗浪一樣訊息如流水,PO文不用一天就會淹沒在訊息洪流中且難以搜尋。動手把去年在FB一堆沒營養嘀咕整理成集,備份Blog留念。

【通勤奇遇】

  • 捷運上坐對面的女生,假睫毛浮誇到我得一直壓抑自己,避免說出:「小姐,別怕,先不要動,妳眼皮上有條蜈蚣,我來幫妳拍掉牠」
  • 捷運站一整排72個車架,只剩一台彈簧脫鉤,中柱故障拖地,沒人要騎的U Bike。但這可難不倒馬蓋先,不慌不忙掏出鑰匙圈串接彈簧與掛鉤,帥氣跨馬上路

  • 快步趕著上班,背後忽然有人追喊: "先生! 先生!"
    回頭一看,一位小姐拿著我的920: "先生! 這是你的手機吧?"
    應該是跑步動作太大,920從背包側袋飛出去,來不及好好道謝,我的小天使就轉身繼續趕路了。
    小姐好人,一生平安~
  • 驚!穿著短褲細帶高跟鞋,一邊坐捷運一邊為整條腿擦乳液...
    相較之下,在電車上補妝根本不算什麼
  • 啊~~~邊趕上班邊想事情,居然把便當+水果+早餐整袋留在 U Bike 的車籃裡 T_T
    末稍血液循環問題真的不容忽略 orz orz orz
    稍後U Bike巡場人員發現我的袋子,客服中心由悠遊卡記錄查到我的電話,通知我東西已寄放在貓纜服務台。超貼心的服務,我流淚了~
  • 在捷運上聽到一名談吐斯文男子打電話詢問坐公車被多扣一段票的退費問題,得到回覆為明天上班時間再連絡負責窗口處理,感覺可能出現通話費大於退款金額的死亡交叉
  • 繼扭到腳切到手之後,今天騎著U Bike在長了青苔的人行道上演出「飄移」,棄車後重心不穩,衝了三四步還是煞不住狼狽跌倒,幸好只是小摔,領回一褲管泥土跟一塊黑青。
    人生真是處處凶險呀~
    回頭牽車看見跟我會車的女生煞車後也打滑車倒,但不忘好心問我:「喂! 你沒事吧?」 忽然有種同為天涯淪落人的溫馨。全程目睹歐吉桑在人行道鏟球的奇景,就當成我給她的回報吧!
  • 上班的捷運上,座位隔壁看書的男孩忽然停下來,默默從包包裡拿出一把大型瑞士刀,拉出小剪刀,用手指點點了站在旁邊的女生,指著她棕黃呢絨大衣口袋上一根5公分的線頭,並指導她小剪刀如何使用。在女孩同行女性友人幫忙下,線頭順利被摘除,但總覺得歸還瑞士刀的道謝神情有點複雜,帶著幾分餘悸猶存。
    說真的,我搞不清楚這是極度熱心還是強迫症,呵~ (更好奇的是,女孩今天的FB會怎麼寫? XD)

【慢跑人生】

  • 乾冷的天氣其實蠻好跑的,但一開始被窩到鞋櫃的十米距離比後來的五千公尺還難跑,很多人要跑半小時以上 XD
  • 坐著打電腦覺得有些冷,起身在座位邊壓25個伏地挺身,馬上全身都暖和了~ 呃,好像哪裡怪怪,正常人應該不會是這樣取暖的吧?
  • 油門催到底,轉速破萬,400米94秒,老爺車的極限差不多就只到這裡了

  • 8月中閒來無事LSD,從政大到永福橋跑完14K,猶豫要折返還是跑到大稻埕再騎U Bike回家?腦波一弱就變成烈日超半馬加鐵馬,最後總算活著回到家,23公里的U Bike騎了兩小時 orz
    心得:「騎23公里」、「跑完超半馬後騎23公里」,跟「跑完超半馬後在大太陽底下騎23公里」是完全不同的三件事
  • 雨後跑上貓空,歷經傷後休養如同砍掉重練,11KM超過一半是用走的,花了一個半小時 orz
    見到柑仔色夕陽是意外收穫,登上貓纜旁的木棧平台,有隻掛狗鏈的大白土狗很兇悍,我一上樓就兩隻前腳搭上我的膝蓋做勢要咬。憑藉過去登山面對野狗的經驗,拎杯也不是省油的燈,右腳用力蹬地做勢要丟東西加上吼聲,大白狗立馬手刀(呃?或者該説腳刀)飛也似地消失在平台上。
    拍完夕陽步下平台,過馬路想丟保特瓶,才走到路中央,背後傳來喘氣聲,腰部被人一推差點摔跤。喵的,光天化日下歐吉桑被人撲倒成何體統?回頭一看,是剛才那隻大白狗,從背後偷襲算什麼英雄好漢?大白狗見我怒氣沖天,不等我跥腳一溜煙又跑了,讓人又好氣又好笑。
  • 舒跑杯10K,第一次全家餐完食!帶小木頭跑步的新體驗:被美少女超車,對方還回頭帶著甜美笑容說「加油哦!」( 我都快融化惹, 臭小孩卻面無表情一臉酷樣)

  • 終於,10公里跑進50分,重要的是眼前沒閃過人生跑馬燈,不容易呀!

 

【小閃光與小木頭】

  • 小閃光問我RGSS3副檔名要用什麼程式開啟?聽都沒聽過,我回說不知道。
    沒多久,她分享新發現,說要用一個紅龍Icon的Game.exe執行,我教她從右鍵內容找到程式描述「Ruby Game Player」,才知有Ruby Game Scripting System這種東西。
    沒想到在家裡也能進行技術社群交流... XD
  • 家長這個職業,歷經伺服器數十年的改版,技能樹是愈來愈發散了。記得以前在玩小孩職業時,沒聽過有什麼萬聖節副本呀

  • 這年頭,若沒有良好體能,是無法勝任「負二代隨扈」這種角色滴

  • 畢業旅行,小閃光第一次單獨離家,我也解除了「叮嚀小孩要打電話回家」的成就。
    望著她的背影,心裡想的是:送她住校、送她出國、送她出嫁的情景也差不多要在我的人生上演囉~

  • 小閃光結束超開心的畢旅,有記得每天打電話回家,還買了擔摟,我也很開心 ^___^


  • "逛遊樂園一整天卻沒坐半項設施"成就解除!
    當父母之後學會的新技能: 聽到小孩笑聲就能獲得與坐雲霄飛車相同的喜悅。
    這些年常憶起童年片段,有些對話與情節,幾十年後類似情境重演,才明白當年爹娘的心情,懊悔自己的渾蛋回應。只可惜就算重來一次,當年的我還是不會懂,正如現在有些話講再多兩個小蘿蔔頭也聽不進去一樣! 人生呀~ 為"養兒方知父母恩"這句俗諺按100個讚。


  • 涼爽午后,在河濱道追著兩個左搖右晃的小背影,不時還得呼喊靠邊慢點---中年大叔專屬,千金不換的「幸福」!

  • 喵的,參加婚禮看到新娘跟家人互動的時刻眼眶又濕了,小閃光嫁人那天要怎麼辦?
  • 平日愛亂看FB、M01跟PTT,學會一堆亂七八糟的東西,我一直以為自己是在浪費生命...
    沒想到今天吃飯跟小閃光聊起美江燒毁R&B,你在大聲啥與公道價八萬一,才知彼此皆鄉民,三十年代溝瞬間消弭~ 只有鄉民,沒有距離!

【時事有感】

  • 不意外地,全都出現了:
    * 新聞詳加報導某人在牢裡睡得好不好,早餐吃饅頭還是稀飯配什麼小菜
    * 民俗大師分析祖厝、祖墳犯了什麼大忌,會招致災禍毫不意外
    * 曾吹捧讚嘆企業主眼光獨到治理有方創建王國簡直奇蹟的雜誌,分析起衰敗原因照樣頭頭是道
    好一堆沒營養的資訊,但念在好多人得藉此養家活口,就不計較太多了。
  • 10元換原燒套餐,民眾半夜瘋排隊… 花6小時的生命賺630元(而且還是市價,不是真實價值),感覺不划算啊!年紀大了之後,愈覺得時間要省點用,分秒得用在刀口上,誰知道哪一天就可能「啵!沒有了」
  • 新戶政系統轉包中國網路公司事件有感:"是國安問題,但國安問題不等於國安局的問題。"瞬間悟道!! 趕快筆記,國安局局長一語突破世人盲點。
    打算貼兩張標語在Partition:
    "是程式問題,但程式問題不等於程式設計師的問題。"
    "是網頁問題,但網頁問題不等於網頁攻城獅的問題。"
    以後日子輕鬆了~
  • 轉自PTT:
    筆電中毒隔天又有報告要交, 只好勇闖資管研究室找專業的救我
    而且還大素顏, 想不到溫馨的資管人們立刻組成維修小組搶救
    然後…我就跟資管人在一起了,目前電腦永久保固中...
    你以為這是阿宅工具人的勵志故事?覺得自己就算只會修電腦訥澀寡言笑,幸福還是會來敲門(握拳)
    等等
    推 detective14r: 維修小組???? 你到底跟幾個結婚啊???
    → warning: 跟負責跟我聊天的那位而已啦
    暗,這根本是鬼故事吧! 這是暗示只會修電腦卻不會哈拉的死阿宅們可以自盡了?
  • 無意間看到「再戰十年」這個PTT流行語,心頭一驚:「老朽還能再戰十年否?」對此開始遲疑,也是一項「中年指標」吧?
  • 歷經多次被指正後,我才確認並不是每個人都會在腦海播放地圖,理解「復興北路往北走」是指哪個方向(尤其是女生)。
    我還以為在某某南北路或某某東西路上用方向指位是最明確,最無爭議的,難道不是?五樓你說說看。
  • 產險公司客服小姐打來做機車強制險線上續保,言明價格比照網路下單,一年折扣120元、兩年優惠180,問我要跟上期一樣保兩年嗎?
    茶包射手: 等等! 一年省120,兩年省180,那我為什麼要保兩年?
    客服小姐: (清了清喉嚨) 呃~ 嗯~ 這樣子可以兩年不用續保... 那... 先生保兩年嗎? XD

【攻城獅內心戲】

  • 補記: 面試到一位求職者,或許因工作環境較封閉,雖然已有多年程式經驗,但對於SQL Injection、連線字串加密、XSS卻沒太多認識。
    一時資安魂上身,特別強調了"拿Request組SQL字串是唯一死刑(阿魯巴到死)"的江湖規矩,也給了幾個關鍵字當成找資料的起點,希望網路世界未來可能的漏洞能再少一點點...
    (但也由此確定,網路世界現存的漏洞比我想的多一點點)
  • 收到HR發信,要求大家連上某個委外網站填表。最重要的是其中有一句:本工具需使用Google Chrome瀏覽器,如您電腦無此軟體,需先下載安裝並執行… (公司內部瀏覽器標準還停在IE8)
    太好了,瀏覽器部署副本有人跳出來當主坦耶~ 以後就可以寫好HTML5網站叫User用「上次HR請你裝的那個Chrome」 XD
  • 我也走到這一步了! 專案裡的CSS繁瑣複雜到自己都受不了,早上花了點功夫摸索並轉成Scss,從今天起,我是會用Scss的前端攻城獅了呢! (撥瀏海) (還沒跟其他Team Member講,會不會被蓋布袋呢?)
  • 在國外網站刷卡後沒多久收到簡訊: 因偵測到異常消費,系統已先將卡片停用,請洽服務中心。
    雖然多一個打電話解鎖手續,但加上保險讓人挺安心,至少遇卡片遺失或被盜刷能很快得知,及早掛失或處理。
    再想深一層: 銀行面對此議題的處置手段有兩種-通知 vs 停用,通知可以省去正常交易也得打電話解鎖的不便,但有被忽略的風險;停用可避免消費者因漏掉通知而擴大損害範圍(其實也在降低銀行吸收盜用損失的風險),但衍生正常交易也得去電告知的困擾。跟系統UI設計時"僅顯示文字 vs alert()/MessageBox.Show()" 的權衡相近。
    二者各有優劣,具有資安偏執的我傾向後者。
  • 不可諱言,國道計程收費系統上線後問題不少,但M01卻一夕之間忽然冒出好多"開發達人"出來酸,指點系統犯了哪些幼稚園學生才會犯的錯,但我深深懷疑那些"達人"們恐怕連"訂便當系統"都沒寫過吧? 做過大系統的人遇到這種案例在一旁心有餘悸,趕緊檢討手上專案設計有沒有類似Issue都來不及,哪來的閒情逸致跑去酸別人?
    程式寫得愈多,就愈不敢輕易罵別人的程式爛,一來是將心比心,二來是會衡量"若易地而處自己能做得更好嗎?" (唯一的例外是SQL Injection,搞出這種漏洞的Programmer人人得而誅之)

【夢醒時分】

具有破解夢境破綻特異功能的茶包射手,與周公的造夢團隊上演諜對諜橋段,一直是本人塗鴉牆的經典戲碼,特完整收錄!

  • 程式寫到一半被拉去討論系統架構,講沒兩分鐘被抓進另一場緊急會議協助排除茶包,白板上的架構圖是防火牆跟IIS Web Farm,苦主說狀況為放寒假後流量變大,部分使用者無法連線(eTag App案翻版?),詢問有無錯誤訊息,苦主稱無,純粹無回應。推測為流量過高導致系統環節崩潰,但不確定是Web還是網路設備(eTag不就是爆防火牆?),建議調閱防火牆及IIS Log比對,追蹤客戶端連入軌跡以釐清問題,苦主說這需要網管配合,於是打電話找來資深網管,網管說防火牆流量極大,保留全部Log有困難,另一方面調閱Log涉及隱私會引發政治議題,偵辦陷入焦著...
    此時發現我的皮夾不見,趕緊回頭往進會議室前的來時路尋找,在市場一個攤販桌(?)報紙下找到,裡面的鈔票全不見了,仔細再翻,找到一張印有「學生票」字樣的百元鈔(咦?),這不是我的皮夾!那我的皮夾呢?
    哼!破碇百出,至此確認是做夢無誤。
    造夢者這回有用心,前半段考證詳實,完全吻合邏輯及技術實務,可惜到後來急著要羅織讓我焦慮的橋段,劇情荒腔走板(該不會是因為前面拖戲太久,後面要趕進度?),可惜了前半段的精心設計。請繼續加油好嗎?
  • 被鬧鐘吵起來,睡眼惺忪地換裝到運動場準備跑它5K,跑前拉筋腦袋一片放空,直到被棒球隊充滿朝氣的口號聲吵醒,發現自己竟在跑道旁打盹了半個鐘頭(囧),這下子也沒時間跑步了。但也開始起疑,等等,這場景不是政大,暗! 我在做夢。
    鬧鐘響了繼續賴床,連在夢中晨跑都會繼續打瞌睡 orz 我累了嗎?
  • 一手滑,920飛了出去摔落地面,觸控玻璃沒破但上下蓋分家,仔細檢查發現接合卡榫的塑膠碎裂,看起來沒法用3秒膠搞定,要破財了,唉!
    等等,現在是清晨天色未亮,手機應該在好好地躺在充電座上,這是夢! 帥氣地把"假"手機往旁邊一扔,哼,管他的。
    (周公: 可惡,又失敗了)
  • 依照慣例,又被困在類似飯店的建築四處找尋特定地點,一摸口袋,暗! 我的手機呢? 回想起剛才去廁所洗了臉,該不會留在洗手檯上?
    立馬拔足狂奔(約莫五分速),依記憶的路線衝回原地點(一路還能很清楚地識別指示牌: 嗯,不是這條,也不是這條,是下一條),接近目標時遠望檯面空無一物,心頭涼了半截...
    不行,掉手機很麻煩,我不要搞丟手機,快給我變出來!
    又更靠近了,檯面有個黑色物體,但體積大了點,是我的Nexus平板? 不對,我要的是手機,是手機!
    抵達檯面時,黑色物體真的變成手機,握在手裡感覺了一下螢幕及背面觸感及電源鈕位置,確認920無誤!
    這回沒靠推理破解,而是成功解除"使用意志力在夢境創造物體"的成就! 我開始具有"原力"了嗎?
  • 好一陣子沒在夢裡找碴了,早上竟出現貓站起來用兩隻腳走路應門還開口說話的鬼扯情節,我也不疑有他... 懷疑自己已喪失做清醒夢的能力。
    但想想不對,我似乎只在受迫情境(處於危機之中,一直自問「怎麼辦?怎麼辦?」)的驚悚片或動作片中才會開啟茶包射手模式,至於文藝片或喜劇,要怎麼瞎扯就隨他吧!(煙)
  • 基於平日維護需要,持有某個祕密地下室的鑰匙,打開鐵閘門換了拖鞋要下樓,怕運動鞋留在外面被人發現,還記得要拿進來放在樓梯間的牆緣,在狹小空間轉身不慎掉了一隻鞋在門外,還來不及回頭撿,就眼睜睜看著鐵門被人從內部遙控關閉上鎖!
    靠腰!今天所有的高階長官全都在地下秘室開會,我怎麼想都沒想就跑進來,要是被發現我有鑰匙可以自由出入就死定了!想到這裡,連心跳都加速了。咦?不對,這是夢,沒事沒事,不管它就好了。
    久違的夢境破解再度登場,但因久未練習,我居然沒推理就真接下結論,觸犯茶包射手大忌,自己都覺可恥,下回改進。
  • 做了個惡夢陷入找不到東西的慌亂,意識到不對勁趕快跳離,醒來看了時間,早上五點二十,起床開始做事,接著出現一些荒謬情節,很快讓我察覺到還在夢裡,決定再醒一次以便逃脫險境,意識稍微清楚後直覺打開手機,3:22!
    第一次精準測得夢境時差,夢裡時間過比較快的說法好像是真的。
    解除「雙層夢中夢連環脫離」的成就,這算人生的新里程碑吧?
    (話說周公的夢境系統看來仍在不斷研發改良,這是2.0 SP1版本吧?)
  • 早起晨跑的計畫失敗了。原因是同事跑來說使用者要求系統開放另一個介面能不輸入CAPTCHA(那種需正確輸入圖片上扭曲英數字才能繼續的機制)就能登入,被我嚴辭拒絕,說開這個後門形同全面失守,盧了很久,我還是堅不退讓。
    情境合理,我又絞盡腦汁忙著解釋漏洞可能造成的風險,沒發現這根本是場夢...
    覺得自己好優秀,連做夢都要堅守資安防線 XD

祝大家新年快樂!


TIPS-為網頁加掛CSS動態更新鈕

$
0
0

改用SCSS後,我在本機測試調整CSS的流程變成:瀏覽器F12開發者工具檢視CSS樣式 –> 回Visual Studio 2013調整SCSS –> SCSS存檔(VS2013編譯產生CSS)—> 瀏覽器重新載入網頁檢視修改結果。由於SPA(Single Page Application)專案每次載入後有一連串起始作業,只為了更新CSS重新載入HTML、重頭執行JavaScript嚴重拖慢開發節奏,做完動作要等半天才能看結果,對急驚風而言宛如酷刑,不另謀改善之道,遲早心臟病發。

Visual Studio 2013的BrowserLink功能強大,能將HTML、JavaScript及CSS修改後自動同步到瀏覽器,也支援靜態HTML檔,理論上適用SPA。或許是程式複雜,遇過幾次跟BrowserLink打架的經驗,反正原理不難,不如就動手做一顆動態更新CSS的小按鈕,順便享受DIY樂趣吧!

操所效果如上圖,在網頁右上方嵌入一個「更新CSS」小按鈕,按下使用JavaScript更改<link href="Content/style.css"> URL,在後方加上亂數Query String,強迫瀏覽器載入更新後的CSS,即可完成動態抽換CSS操作。程式範如下:

<!DOCTYPEhtml>
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test</title>
<linkhref="Content/style.css"rel="stylesheet"/>
<scriptsrc="Scripts/jquery-2.1.1.js"></script>
</head>
<body>
<div class="title">darkthread</div>
<script>
        $(function () {
var $btn = $("<button>更新CSS</button>");
            $btn
                .css({
                    position: "absolute", "z-index": 100,
                    top: "6px", right: "6px", fontSize: "9pt"
                })
                .on("click",
function () {
                    document.getElementsByTagName("link")[0].href =
"Content/style.css?_=" + Math.random();
                })
                .appendTo("body");
        });
</script>
</body>
</html>

【茶包射手日記】失控的position: absolute

$
0
0

接獲報案,某個使用jQuery blockUI的網站,在呼叫$("#someDiv").block()時,遮罩沒放在<td>的正上方,跑到更上層容器的左上角。

問題只出在某個部門的數台機器,其他部門均操作正常,開F12開發者工具由IE相容模式列表檢查IE版本,正常與異常案例都是IE8(公司瀏覽版標準仍停留在IE8 orz)原本以為是blockUI計算遮罩位置時,因某些特定環境形成誤差。再深入調查,發現blockUI的原理是將待遮蔽容器的position設為relative,在容器中新増三個新元素<iframe>(避免老IE <select>打破z-index規則浮至最上層)、半透明遮罩div、訊息內容div,並將其設定為position: absolute,width: 100%,height: 100%且z-index > 1000,讓新元素佔滿容器全部面積並浮在容器上方,以形成遮蔽效果。為求單純,我將blockUI的遮罩元素直接寫死在HTML裡,做出能重現問題的範例:

第二個<tr>第二個<td>設定為position: relative並加入position: absolute <IFRAME>跟兩個<DIV>,理論左上角應與該<td>對齊,卻硬是跑到第一個<tr>第一個<td>的位置,也就是整個<table>的左上角。試著將<IFRAME>等移到第三個<tr>第四個<tr>,出現位置永遠都在<table>左上角。

至此,鐵證如山,問題鎖定在「問題IE未正確實現postion: relative及position: absolute規格」!IE8你在搞什麼鬼?隨手檢查IE版本,嚇得我屁滾尿流失了魂~~

是誰?為什麼到現在還讓機器跑IE8 RC1?誰還我數小時的青春?

【教訓】別由F12開發者工具的相容模式清單識別IE版本,請明確檢查IE版號!你永遠不知道戰場上會遇到什麼埋伏…

【茶包射手日記】SQL連線失敗疑雲

$
0
0

測試台的登入API突然出現失敗,追至上游在Log發現錯誤訊息:

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 0 - An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.)

依經驗,前半段是SQL Server未開機或無法建立網路連線的標準訊息,但後方"because the system lacked sufficient buffer space or because a queue was full."卻很罕見,查到MSND Blog,有兩種可能:OS的TCP Buffer記憶體耗盡,或是TCP的臨時Port號用光了(Windows 2003/XP只有5000個可用)。初步觀察,用netstat檢查當下連線不到20條離上限仍遠,至於TCP Buffer耗盡疑慮則沒找到明確線索證實或排除。找出該API要連線的SQL IP,由其他主機試連OK,因此排除SQL Server端網路出狀況的可能性,聚焦回到API主機端的網路。試著修改API服務加入追蹤Log,再得到不同的誤訊息:

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 0 - Only one usage of each socket address (protocol/network address/port) is normally permitted.)

由"Only one usage of each socket address (protocol/network address/port) is normally permitted."查到MSDN文件,問題根源再次指向TCP Port號用完,且於API主機試連其他台IIS(telnet xxx.xxx.xxx.xxx 80)也出現無法建立連線錯誤,確認問題出在API主機無法建立對外連線(但可以順利透過VNC連上它遠端遙控偵錯,顯示對內連線未受影響),反覆測試telent偶爾成功,多數失敗,推測可能剩餘TCP Port號或Buffer資源有限,故成功靠運氣,但netstat並沒看到成千條並存連線,缺乏佐證。

問題在重新開機後消失。重開機時TCP等資源會全部重設,Port或Buffer不足狀況消失,一切恢復正常很合理。但先前未由netstat印證資源被大量連線吃光,真相成謎,先歸入X檔案~

【茶包射手日記】專案編譯出現「缺少ExtensionAttribute ctor」錯誤

$
0
0

用Visual Studio 2013開啟某個古老VS2010專案,編譯時爆出以下錯誤:

Missing compiler required member System.Runtime.CompilerServices.ExtensionAttribute..ctor

爬文找到一些討論(12),歸納如下:

主因為System.Core引用版本錯誤,ExtentionAttribute是3.0起新増的型別,故常發生於由2.0升級至3.0/3.5的.NET專案,程式使用擴充函式,專案參照仍使用2.0的System.Core造成問題。

檢視問題專案已是.NET 3.5,是否先前由2.0升級3.5已不可考,而該專案引用不少其他程式庫,其中有些仍為.NET 2.0,吻合網路討論所提2.0/3.0+版本混淆情境。但由Visual Studio檢視專案參照的System.Core版號已為3.5,會何抱怨缺少宣告?原因不明。


網路討論提到一些解決方式:

  • 重建3.5新專案再一一搬入項目
    工程耗時,未嘗試
  • 移除造成問題的特定DLL(蠻多案例起因Json.NET之前的某個版本,但現已修正)
    我的案例沒用到Json.NET,而是專案自己宣告了擴充方法(Extension Method)。試著移除擴充方法與相關程式碼,問題便消失,但在本案例中不算解決方法。
  • 將專案設成2.0編譯一次(編譯失敗,但無妨),再切回3.5
    測試無效
  • app.config加入<bindingRedirect oldVersion="2.0.0.0-2.1.0.0" newVersion="3.5.0.0"/>
    測試無效(依我理解,bindingRedirect應該只在執行階段生效才對)
  • 移除System.Core參照並重新加入
    重新加入System.Core參照會跳出該參照已內建的訊息
    A reference to 'System.Core' could not be added. This component is already automatically referenced by the build system.
    專案移除System.Core參照,Missing compiler required member錯誤訊息不變。
  • 手動補上public class ExtensionAttribute
    最後找到可行解法:在專案裡找地方宣告一個空的System.Runtime.CompilerServices。ExtensionAttribute。
    namespace System.Runtime.CompilerServices
    {
    publicclass ExtensionAttribute : Attribute { }
    }

FIX4FUN-斷傘維修日記

$
0
0

好好一把新傘,剛按下開傘鈕就在小閃光手上折技,誇張地攔腰分屍(這孩子天生神力來著?):

雨天臨時買的廉價應急傘不能苛求品質,脆弱到沒上戰場就陣亡未免太扯。但依常理,此時正常人應一笑置之丟了就算,偏偏某中年人最近買了號稱地表最黏的金剛固力膠(示範影片12),加上骨子裡「把東西修好」的工程魂大爆發,竟做出不符投資報酬率之舉-為破傘進行器官移殖實驗。(其實是想測試膠水的能耐啦)

家裡剛好有另一把準備要丟的雨傘,傘骨開花但中棒(主心骨)完好(參考:雨傘構造),比對過傘柄處的彈簧卡榫尺寸相近,符合器官捐贈條件,蒙古大夫抄起鋼鋸馬上動手術。有個小問題是要殖入的中棒鐵管口徑較小,插入後空隙略大不利黏合固定。心生一計,間隔式纏上環狀膠帶,增加內外管密合度但要露出足夠金屬表面。固力膠硬化會膨脹,在狹小空間膨脹剛好向內外抓緊金屬面,接觸面積愈大接合效果愈好。

上膠後新舊傘管結合,算準卡榫位置,用膠帶固定靜置一晚…

隔天答案揭曉,卡榫位置正確,雨傘收合沒問題。接合處很牢固,用力推拉也不會位移,判定修復成功。

順便做了5公斤承重測試。(其實我還試了10公斤裝水水桶也過關,但感覺塑膠傘把部分會先斷,測試緊急喊卡 XD)

植物嫁接技術創新應用成功範例,獨一無二,上黑下白馬來貘風造形傘誕生~

舊傘零件 免費,廉價雨傘 99元,固力膠 189元,把東西修好的成就感,無價!

但,小閃光應該會嫌撐著上街丟臉不敢再用吧?哈!(我敢,而且還要很驕傲地撐,這可是拎杯鬼斧神工修好的哩~果然,「工程師跟你想的不一樣」 XD)

如何選擇程式語言?(中文版)

$
0
0

寫程式已經成為全民運動,連歐巴馬都下海了

前幾天在FB看到一則貼文分享,部落客Carl Choe做了一張「如何選擇程式語言?」流程圖,依學習動機、鎖定的平台產業、想上班的公司…等等,建議初學者如何在Python、Java、C、C++、JavaScript、C#、Ruby、PHP及Objective-C等語言間做出抉擇,裡面還用魔戒角色妙喻不同語言,讓程式老骨頭會心一笑。徵得作者同意,我將它翻成中文版(嚴格來說是台灣鄉民版 XD):

這裡看原尺寸圖檔 1666x1841

節錄我覺得最有趣的部分-程式語言與魔戒角色對照:

  • Python 樹精
    幫助哈比人(初學者)了解程式概念
    幫助巫師(電腦科學家)進行研究

    普遍認定為初學者最佳入門 語言
    最容易學習
    廣泛應用於科學、技術與學術領域,例如: 人工智慧
    如要建立網站,Python上有Django架構可用
  • Java 甘道夫
    愛好和平,並與每個人攜手合作(可攜性)
    具備優異的可攜性,在所有平台、作業系統及各種裝置上都可通行無阻
    工作機會最多及待遇最好的程式語言之一
    Slogan: Write Once, Work Everywhere.
    口號:只要寫一次,到處都能跑
  • C 魔戒
    每個人都知道C的厲害
    每個人都想擁有它的力量

    程式語言界的國際語言
    最古老且最廣泛使用的語言
    大量應用於系統軟體及硬體程式開發
    可視為C++的子集合(但有些微差異)
  • C++ 薩魯曼
    每個人都覺得他是好人
    多認識他一點,就會發現他想擁有力量,不是個好東西

    C的複雜版,加入不少強化
    廣泛應用於遊戲、工業及講究效能的程式
    學習C++如同學習如何製造、組裝及駕駛一輛汽車
    建議找個導師引你入門
  • JavaScript 哈比人
    力量常被人低估
    給人「住在夏爾(瀏覽器),悠閒慢活度日」的印象

    Java與Javascript的相似度,差不多相當於牛與牛蒡間的關係
    最流行的網頁前端程式語言
    前端工程師的必備技能(還有HTML及CSS)
    當前最火紅的語言之一, 並逐步拓展到後端(node.js)
  • C# 精靈
    美麗的生物(語言),但只待在自己的Rivendell王國(微軟平台)
    註: 此點在.NET開源之後將有所改觀
    企業使用.NET平台建立網站及Windows程式的最主要選擇
    可使用ASP.NET(微軟推出的網站架構)打造建置網站
    在基本語法及一些特性上與Java相似
    如果所開發程式以Windows平台為主,學C#準沒錯
  • Ruby 人類
    情感動物(語言)
    他們(部分 Ruby開發者)覺得自己高人一等並負有統治中土的使命

    以大受歡迎的網站架構Ruby on Rails(RoR)聞名
    聚焦於快速搞定
    開發過程有趣且具高生產力
    個人閒暇專案、新創公司、快速開發的最佳選擇
  • PHP 半獸人
    醜八怪 (語言)且不尊重規範(缺乏一致性,難以預測)
    (程式碼)難以管理,讓其他人(開發者)頭痛不已

    但對中土仍然很有貢獻(最普遍的網站開發語言)
    適合在很短時間內建置出小型簡單網站
    容易找到網站寄放空間(Web Hosting Service),而且費用低廉
  • Objective-C 史矛革(噴火龍)
    孤獨而拜金
    Apple主推,Mac OS X及iOS的主要語言
    如果你聚焦於開發iOS或 OS X App,選擇它就對了
    可考慮改學Swift (Apple 於2014推出) 做為下一個語言

魔戒角色比喻很有趣,但不少是作者的主觀看法及幽默,大家輕鬆看待就好,不然戰十天十夜也戰不完。倒是翻譯下來,重新認識了Python這個語言,前陣子在玩Raspberry Pi時剛好有接觸到。若依文中所提,Python非常易學好上手,學會等於在Linux平台有了寫小工具的腳本利器,值得關注。

個人英文能力有限,加上死性不改硬要亂加鄉民用語,翻譯不周之處歡迎留言回饋,但請大家鞭小力一點囉~

NG筆記21-Angular 1.3對Filter的強化

$
0
0

Angular不需宣告observable就能實現屬性連動,背後靠的是Dirty Check機制的反覆比對,代價是產生許多無謂計算(延伸閱讀:保安,可以讓Angular這樣算了又算算了又算嗎),而好用的Filter特性也在無謂重算之列。當我們寫"{{ propA | convFormat }}",當NG要檢查「是否有任何數值發生變化」時,就得將propA傳給convFormat重算結果。Dirty Check重算檢查的頻率或許比大家想像得多,propB、propC或procD屬性改變、ng-click/ng-blur/ng-keydown/ng-mousedown等事件被觸發,或是$http完成AJAX呼叫,以上每一個動作都會引發重算。

用實例來驗證這點:

<!DOCTYPEhtml>
<htmlng-app="app">
<head>
 
<metacharset="utf-8">
<title>Filter執行頻率示範</title>
<style>
    input,div { display: block; margin: 12px; }
</style>
</head>
<bodyng-controller="ctrl as m">
<inputng-model="m.text"/>
<inputng-model="m.other"/>
<inputtype="button"value="Do Nothing"
ng-click="m.doNothing()"/>
<div>
    by filter: {{m.text|sayHi}}
</div>
<div>
    by $watch: {{m.message}}
</div>
<scriptsrc="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script>
function MyCtrl($scope) {
var self = this;
      self.text = "Jeffrey";
      self.other = "blah";
      self.doNothing = function() { };
      self.message = "";
      $scope.$watch(
function() {
return self.text; 
        }, 
function(newValue) {
          console.log("watch-changed")
          self.message = "Hi, " + newValue;
        });
    }
    angular.module("app", [])
    .controller("ctrl", MyCtrl)
    .filter("sayHi", function() {
returnfunction(value) {
        console.log("filter-exec");
return"Hi, " + value;
      }
    })
</script>
</body>
</html>

Demo

在範例中,text為目標屬性,用以保存姓名,最終目標要顯示"Hi, " + text。程式示範了兩種不同做法:

  1. 宣告sayHi Filter,透過{{ m.text | sayHi }}轉換成"Hi, " + text
  2. 多宣告一個message屬性,使用$wath()追蹤text,text異動時更新message為"Hi, " + text

我們分別在sayHi Filter及$watch()中加入console.log(),藉以觀察二者被執行次數。另外再抓兩個路人來當臨演:other屬性以及ng-click動作doNothing()。方法2較囉嗦,但優點是它只有在text變動時才執行字串相加邏輯。而sayFilter除了text變更後跑兩次(一次被text更新觸發,另一次源自Dirty Check重算),在other改變及ng-click時也會重跑。如以下操作展示:

字串計算耗用資源有限,多算幾次差別不大,但若換成更複雜的運算或是更高頻的Dirty Check環境,就足以形成明顯效能差異。

針對這點,Angular 1.3做了一些改良,讓Filter變得更聰明!從1.3起,Filter會Cache計算結果,若來源資料不變就直接使用Cache內容,省去無謂重算。沿用前述程式,只將Angular由1.2.26換為1.3.0(2015年1月已到1.3.2版,但此處用1.3.0證明變化從1.3開始),實測可發現結果明顯不同:Demo

sayHi Filter函式執行時機變得跟$watch()一致!只有在text改變時執行,不受other屬性及ng-click事件影響,Angular 1.3+的Filter真的變聰明了!

【結論】從Angular 1.3起,我們可以更放心大膽使用Filter,不必再為了效能刻意改寫成$watch囉~
(註:若此一行為改變造成舊程式崩壞,可在Filter中設定$stateful參數,恢復成1.2.x的行為模式)

[NG系列]

http://www.darkthread.net/kolab/labs/default.aspx?m=post&t=angularjs

【茶包射手日記】IE CORS跨網域存取的特殊規則

$
0
0

同事報案,安裝SPA專案在localhost,跨網域發出AJAX請求到ServerA時出現存取被拒訊息,而該情況獨獨出現於IE11,Chrome與Firefox並無問題。

排除Web API端的CORS配套機制的問題(由Chrome及Firefox具名擔保,延伸閱讀:CORS OPTIONS Preflight Request與IIS設定),且更玄的是問題只發生在同事的IE11,在我的IE11測試本機localhost SPA專案發送同樣的AJAX需求到ServerA,一切正常。

經過一番診察,濃縮出檢測問題的極簡步驟-在F12開發工具主控台下指令$.post(httq://172.28.1.1/cors/chart/getdata, {}),正常狀況應出現CORS請求訊息如下:

失敗案例則被IE11直接拒絕,連嘗試送出Request的動作都沒有。

爬文在Stackoverflow找到一則相關討論,我注意到裡面有一段描述:

Internet Explorer has two major exceptions when it comes to same origin policy:

  • Trust Zones: if both domains are in highly trusted zone e.g, corporate domains, then the same origin limitations are not applied
  • Port: IE doesn't include port into Same Origin components, thereforehttp://company.com:81/index.html and http://company.com/index.html are considered from same origin and no restrictions are applied.

發現關鍵字「信任的網站區域」。檢查同事的IE11,果然找出差異:同事的IE11將ServerA設為信任的網站,我的IE無此設定,故ServerA被歸於網際網路。區域設定為IE的專利,這解釋了為何問題只發生在同事的IE,我的IE及Chrome與Firefox都正常。

但仍然有疑點,前述Stackoverflow討論只提到同屬信任網站不算Cross Site,未能解釋為何近端內部網路存取信任網站會直接被拒絕?

再用關鍵字查到一篇文章,提到IE10+有項特性:當Origin(執行發出AJAX呼叫的一方)與Host(提供資源的一方)二者只有一個在信任的網站區域,另一個不是時(例如:Origin為受信任網站,Host為近端或網際網路;或Origin為近端或網際網路,Host為受信任網站),會產生我所觀察到的存取被拒。而經實驗證實:將localhost加入信任的網站或將ServerA移出信任的網站,CORS運作便會正常。

由前述文章再找到MSDN文件,才算真相大白:

  • Cross-domain requests are allowed within the same zone if the Internet Explorer security manager has allowed "Access data sources across domains" (URLACTION_CROSS_DOMAIN_DATA) either implicitly or by prompting the user.
    當跨網域請求發生在同一區域,由IE安全管理員決定是否允許。(包使用CORS OPTIONS詢問)
  • If the request is from a more trusted security zone to a less trusted one, the security settings of the originating zone apply. (The security zones, in order of trust, are as follows: Local Machine, Trusted Sites, Local Intranet, Internet.)
    當一個較安全區域向較不安全區域發出請求時,安全原則依較安全的一方決定。
    各區域的安全強度依序為本機(Local Machine,注意,本機並不是指localhost,而是以file: /// URL開啟本機資料夾的網頁,參考)、信任的網站、近端內部網路。
  • All cross-domain requests to or within the Restricted Sites zone are disallowed, regardless of selected security zone policy.
    與限制的網站相關的跨網域請求將完全被禁止。

文章附了一張表,其中有一項重要原則-所有由較不安全區域跨網域存取較安全區域資源的行為都是被禁止的,例如:由近端內部網路存取信任網站、由網際網路存取近端內部網路…都將被拒絕。

回到我們的案例,SPA網頁在localhost執行被歸為近端內部網路,當ServerA被設為信任的網站,localhost向ServerA發出跨網域請求,就觸犯了「由較不安全區域(近端內部網路)向較安全區域(信任的網站)發出請求」的禁令,這就是IE直接拒絕該請求的依據!同時我也補做實驗,反過來將localhost設為信任的網站,將ServerA設為近端內部網路,測試CORS存取可成功,理由是情況已被逆轉為由較安全的區域向較不安全區域發出請求。因此,先前提到Origin與Host必須同屬一個區域的假設不完全正確,正確的說法應是「Origin與Host必須同區域,或者Origin所處區域的安全強度較Host來得高」。

又解開了一個謎團,感覺真好!

NuGet Packages資料夾該不該加入TFS版控?

$
0
0

這年頭用Visual Studio寫程式已經離不開NuGet了!NuGet會在每個專案新増packages.config記錄已安裝Package及版本,在解決方案(.sln)檔所在資料夾則會建立packages保存各專案的NuGet Package DLL實體,放在解決方案層級的好處是方便Package檔案共享,專案A裝過NLog,專案B要安裝NLog時就不需要重新下載,直接參照packages裡的nlog.dll就好。除了packages目錄,如果選擇Enable NuGet Package Restore,還會再多一個.nuget資料夾,裡面有NuGet.exe、NuGet.config、NuGet.targets,方便建置時自動由NuGet補足缺少的Package。(但此點不適用Web Site Project)

使用NuGet Package Restore可減少原始碼傳送及封存時的資料量。packages資料夾包含大量dll檔,容量常常高達數百MB,啟用Package Restore後,packages不需隨原始碼打包,對方可在建置專案時再由NuGet即時下載安裝。

「packages跟.nuget資料夾該不該進版控?」的問題困擾我好一陣子了,之前沒掌握底層運作的眉角,常被一些「靈異現象」整得七葷八素,直到累積一些心得後,才有較具備的概念!(老話一句,會覺得「暗!見鬼了」多半是因為了解不夠透徹,線索掌握不足所致,真相大白後便會驚覺一切都符合科學邏輯,電腦永遠是死板板照指令辦事,從不背叛任何人。相較於江湖事,單純豈止十萬倍? XD)

packages進版控跟不進版控實務上都可行,但屬兩種不同策略,實踐時一些細節要到位,不然會搞到你欲哭無淚。

策略一:packages不進版控

記得要開啟Enable NuGet Package Restore選項,並確認packages目錄沒有簽入TFS。之前遇過案例:package被誤簽入TFS,但預設dll、exe檔案型別不會簽入。因此TFS版控空有packages各Package的完整目錄結構,獨缺最重要的dll檔。另一位同事取得最新版本編譯專案,NuGet試著還原Package,發現該Package版本的目錄已存在於packages,便認定已下載略過還原程序。結局是專案依循參數路徑找不到dll,若不是直接報錯,就是靠Visual Studio顯神通找到自以為合用的dll頂替,搞出靈異現象

方法二:packages進版控

如果想避免重複下載Package,或是建置環境無法連上NuGet,則可選擇將packages全部簽入TFS版控。如此另一方在取得最新版原始碼時,所需NuGet Package dll檔一併就位,直接編譯即可,不需再花功夫下載。

但有幾點要注意:

  1. 如果已Enable NuGet Package Restore,.nuget資料夾也要簽入
    新版NuGet會在csproj中加入以下檢查,Visual Studio能自動補上.nuget資料夾,但使用MSBuild編譯時便會因.nuget不存在而出錯。
    <TargetName="EnsureNuGetPackageBuildImports"BeforeTargets="PrepareForBuild">
    <PropertyGroup>
    <ErrorText>This project references NuGet package(s) that are missing on 
    this computer. Enable NuGet Package Restore to download them.  For more 
    information, see http://go.microsoft.com/fwlink/?LinkID=322105. 
    The missing file is {0}.
    </ErrorText>
    </PropertyGroup>
    <ErrorCondition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')"
    Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))"/>
    </Target>
  2. 簽入.nuget、packages時要確認有包含dll及exe
    預設TFS在簽入資料夾時將排除exe及dll,要記得將它們從排除清單(Excluded items)再拉回來。
     
  3. NuGet Package新増或升級時記得簽入TFS
    由於不再依賴NuGet自動補檔與升級,Package如有異動記得要簽入

TypeScript 1.4升級通知

$
0
0

同事報案,下載Angular TypeScript定義檔後,jQuery.d.ts出現大量錯誤訊息,無法編譯:

看了錯誤所在,出現U|JQueryGenericPromise<U>的新奇寫法,先前在Kendo UI討論區發問曾聽Telerik RD提過,這似乎是Union Type新語法。TypeScript檔是1/22新出的,推測有加入新語法導致錯誤的可能。由TypeScript官網找到VS2013套件下載連結,證實TypeScript 1.4版已於1/17釋出。

安裝1.4版後重開Visual Studio 2013,程式詢問是否要升級csproj所使用的TypeScript版本?(不升級定義檔Build不過呀… orz)

定義檔的所有錯誤在升級VS2013 TypeScript套件後消失無蹤。所以故事是:TypeScript於1/17升級,1/22釋出的jQuery定義檔已改用新版語法,手腳超快呀!讓人有「音浪太強,不晃會被撞到地上」的感覺~

至於TypeScript 1.4的新功能,可以看MSDN Blog的這篇介紹,Union Types克服「有兩種以上可能型別的變數只能改用any不做控管」的缺點,是一大革新!另外,Type Alias讓複式型別引用時更簡潔,也很好用。

因為定義檔已改用新版,如果不打算更新TypeScript編譯器,記得要保留舊版定義檔。不過,TypeScript 1.4的Union Types跟Type Alias是很好用的重大革新,值得儘快更新!

音浪太強,不晃會被撞到地上~ 音浪太強,不晃會被撞到地上~

【茶包射手日記】.NET程式被判定不是有效的 Win32 應用程式

$
0
0

接獲報案,某隻.NET程式在本機測試正常,同一個EXE檔搬到特定幾台機器,一執行就出現"is not a valid win32 application"(中文版為"不是有效的 Win32 應用程式")。

問題機器為32位元Windows 2003,上面已經有多個.NET寫的排程程式運行中,檢查Windows\Microsoft.NET\Frameworks目錄,v1.0到v4.0.*資料夾都在,判斷已裝到.NET Framework 4.0,而另外寫一個簡單.NET 4 Console Applicatione測試程式丟上問題機器可正常執行。原本一度懷疑問題主機中毒,放上的exe被篡改導致檔案毁損(訣竅:這年頭不管出了什麼事,讓駭客出來揹黑鍋就對了 XD),.NET 4測試程式執行成功已大致排除中毒疑慮。(駭客:看!你有問題關我屁事?)

好奇用Notepad++開啟問題程式及測試程式的exe二進位檔,想粗略檢查MZ表頭結構是否異常,意外發現問題程式exe檔末端出現Framework,Version=v4.5字樣。追問程式來源,確認這個專案被編譯成.NET 4.5!

原先沒料想該程式用到.NET 4.5,知道Windows 2003不支援.NET 4.5,也知道x86/x64版本不合時會冒出不是有效Win32應用程式錯誤,但.NET 4.5程式在Windows 2003平台出現此一訊息倒在意料外!將先前成功執行的.NET 4測試程式換成.NET 4.5,刻意編譯成x86平台,放到Windows 2003執行可重現相同錯誤,驗證「在Windows 2003主機上執行.NET 4.5程式會出現"不是有效的Win32應用程式"錯誤」。

筆記之。

2015櫻花馬

$
0
0

再次重返初馬聖地,雙溪櫻花馬成為我的第21馬!

初馬的十度低溫與淒風苦雨記憶猶新,隔年則是豔陽高照的好天氣,去年缺席,今年又輪回寒冷陰雨,但賽期搭上櫻花季,想必是場櫻花味十足的馬拉松~

馬跑多了,愈來愈平常心,賽事自動區分兩種類型:一種是博命演出拼PB,一種則是吃喝玩樂兼賞景,徹底兩極。櫻花馬有櫻花有補給有山景,自然是後者無疑。 XD

7點左右到達會場,雙溪高中,寄物處設在體育館內,空間廣大又不淋雨,很棒的規劃。等待起跑期間雨勢時大時小,看來今天註定是場充滿「濕意」的賞花行程,躲在司令台旁的初馬獎發放空帳篷避雨,邊聽主持人廣播。

大會報告一再重申不得代跑配掛他人晶片(違者失格並禁賽)、號碼布一律別在前方才准通過感應帶、嚴格執行關門時間一秒鐘都不寛貸、路跑社團有偷搬其他帳篷桌子的快還來、廠商車輛違停請趕快移開、配速員請快點上台(否則取消資格不用來)、賽道有經過精確測量且每公里都有標示牌。強烈感受到北馬主辦的一絲不苟、紀律嚴明、高道德標準,我喜歡!哈。

會場有個Kudo版的蘭平千里碑,署名雙溪硬化馬,很有趣。

開賽前遇見啟發我投身路跑的前輩兼知名部落客(說知名不誇張,現場還真有讀者跑友與他相認,呵),既然兩人都無意拼成績,就相約跑聊天馬,當成一場氧健身LSD吧!

8:30準時出發,五千多人的大賽事(初馬超過二千人),人山人海。

今年的賽道跟我前兩次跑的不完全相同,但九公里連續上坡仍是原汁原味,全無偷工減料。但邊聊邊跑,心境不同,倒也輕鬆愉快。

賽道設計成一線到底原路折返,共計六個水站,21切成七等分剛好每3公里一個。

在補給站發生一件趣事。賽前大會報告提到配合濕冷天氣補給站備有熱食,便特別留意尋找。見到某帳篷前選手聚集處白煙裊裊,想必有熱食好料,擠進去看發現只有沙士汽水,哪來的熱食?再定神一看,才發現白煙是天冷跑者身上冒出的水蒸氣… 哈,笑翻了!(今年補給品有香蕉、橘子、77乳加、小餐包、小蕃茄、鹹蛋、沙琪瑪、薑茶、豆干、桂圓湯、味增湯、水、運動飲料、沙士、咖啡,我沒逐站細查,可能有漏)

碰上花期,一路都有山櫻李花可看,李花(照片裡的白色花)比山櫻花形大且密集,更為搶眼,回家整理照片發現李花拍得比山櫻多很多。

 

 

 

 

近21K折返處進入宜蘭縣的範圍,交界處宜蘭縣道0公里路標與新北市界碑交會,見證我們從新北市跑到宜蘭縣再跑回新北市,呵。

 

照慣例要拍32K里程牌,象徵本場馬拉松比賽正式展開!

天氣濕冷,但雨勢不大,比起2012初馬那年來得小,證據是今年鞋子沒濕。基本上老天爺還是給了個不錯的跑馬天,但一路上很多時候會跑進雲裡。

 

成績不放在心上,一路跑來心率不高,算是輕鬆愉快(但腿腳微酸難免),最後以5:52:41(大會時間,GPS錶計時約5:50:15,晶片時間則要等大會寄成績電子檔)再下一馬。

題外話,老錶GH-625M電池充滿電撐不到六小時就出現電量不足,應是電池老化,真傷腦筋。(謎之聲:哼!嘆氣時還嘴角上揚,明明偷笑想買新錶吧?)

賽後領到大浴巾、福隆便當、礦泉水及一包能量飲。

完賽獎牌設計成項鏈造型,相當獨特。(跑友們反應蠻兩極的)

臨走前接近6小時40分的關門大限,便留下來見證獅子頭大哥的關門鐵腕,最後十秒倒數計時,時間一到立刻關門放狗撤除計時感應,收掉獎牌,被關門的跑友只有浴巾,沒有成績,沒有獎牌。

影片

該不該基於人情給辛苦拼完42公里的逾時跑友多一些寬容,贊成或反對的聲音一直都在。我個人覺得,既然明訂規則在先,嚴格執行關門為完賽獎牌增添幾分得來不易的價值感(想像一下「排兩小時隊買到限量版專輯,一轉身發現隔壁唱片行正在買一送一」的感覺),付出汗水努力達成可受公評的目標,才會讓完賽獎牌真正綻放光芒~

Viewing all 2433 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>