Skip to content

zh

使用PredictionIO的啤酒推薦引擎

問題:

我們都愛啤酒。然而,今天我們面臨的是前所未有的選擇多樣性,讓我們感到不知所措和猶豫不決:我們下一個該喝什麼?

我的解決方案:

在我們的Hack Reactor論文計畫中,我構建了一個使用PredictionIO作為啤酒推薦引擎的機器學習服務器。廣義地說,該應用基於兩個主要策略:

  1. 內容過濾方法:這使用每種啤酒的各種特性來識別其性質。例如,我們利用breweryDB來確定特定啤酒的風格,其酒精度(ABV)和其國際苦味單位(IBU)。然後我們查詢數據庫以找到風格相似的啤酒。

  2. 協同過濾方法:這完全依賴於過去的用戶行為,特別是你的啤酒評級。它使用交替最小二乘法(ALS)算法的矩陣因子分解技術。我們通過從啤酒評級模式中推斷出來的因子向量來描述啤酒和用戶。啤酒和用戶因子之間的高度相關性將導致推薦。

使用矩陣因子分解的一個優點是其能夠加入附加資訊。當沒有顯性反饋(即,你的評級)時,我們可以使用隱性反饋,如你的瀏覽歷史和搜尋模式,來推斷出用戶偏好。

結果,OnTapp將你和適合你口味的啤酒配對起來。要獲得啤酒推薦並嘗試我們的示例,請訪問:http://ontappapp.com/.

AngularUI:處理Google地圖標記的滑鼠懸停事件

問題:

我花了一些時間才弄清楚這個問題,所以我覺得這個問題值得一篇自己的博客文章。當我試著用AngularUI連接Google Map標記的滑鼠懸停事件時,我發現自己很困惑。文件在這件事情上很含糊,說它只支援單一標記,而不支援多個標記。

對於單一標記,只需要在HTML中指定一個帶有 events 屬性的指令就很直接:

<ui-gmap-marker events="marker.events"></ui-gmap-marker>

然後在控制器中:

$scope.marker = {
  events: {
    mouseover: function (marker, eventName, args) {
      // 回調代碼在此
    },
  },
}

然而,相同的做法不適用於多個標記。我最初以為我可以簡單地為每個標記添加滑鼠懸停事件,就像這樣:

markers.push({
  events: {
    mouseover: function (mapModel, eventName, originalEventArgs) {
      console.log("I'd really like to show the info window on mouseover.")
    },
  },
})

我的解決方案:

為了解決這個問題,將以下內容添加到HTML markers 指令:

events="clickEventsObject"

並在控制器中:

$scope.clickEventsObject = {
  mouseover: markerMouseOver,
  mouseout: markerMouseOut,
}

function markerMouseOver(marker, e) {
  // 回調代碼在此
}

function markerMouseOut(marker, e) {
  // 回調代碼在此
}

它成功了!這個處理程序返回一個直接映射的模型陣列,該陣列屬於與事件一起發送的gMarker集群。如果你有任何問題,請隨時向我提問。😊

找出2015年新年決心的竅門

當一年即將結束,新的一年在1月1日開始時,許多人會設定新年決心。然而,92%的新年決心最終都會失敗。為什麼會這樣?

這個問題引起了我的興趣。以我的黑客思維,我喜歡將問題解決技巧應用到各種情況中,如果能突破這8%的成功率,我會非常高興。

研究顯示,'意志力'可能是一種有限的資源。我們都渴望改進自己,但僅靠意志力往往不足以達成目標。未能達成我們的目標可能會讓人沮喪,導致一種自我批評的循環,這並不幫助我們前進。

要產生有意義的變化,我們需要保持我們的目標既簡單又可實現。解決手邊易於應對的問題,可以提供繼續前進的動力。將模糊的抱負轉化為具體的目標並每天為之努力是很重要的。畢竟,我們是我們重複行動的總和。因此,卓越更多的是一種習慣,而非孤立的行為。

我的年度目標

為保持自己在正軌上,我制定了每日待辦事項,包括:

  1. 始終保持編程- 每天至少花一個小時解決玩具問題或接受編程挑戰。

  2. 優先考慮身體健康 - 每天花30分鐘慢跑或做其他運動。 健康的身體養育健康的心靈。

  3. 致力於學習- 每天花一個小時閱讀書籍或觀看教育影片,擴展你的知識。

  4. 加強社交網絡- 每天花一個小時和家人或朋友聯繫,無論是在午餐,晚餐,或一次簡單的聊天。

Angular.js 工廠:異步處理 $http

問題:

當我使用 $http 服務從遠程API獲取數據時,下面的代碼片段無法將數據返回到控制器。

myApp.factory("myFactory", function ($http) {
  var data = { anArray: [] }

  $http.get("/api").success(function (response) {
    data.anArray.push(response)
  })

  return data
})

這個問題的出現是因為在 $http GET請求將數據推送到數組之前,就執行了 return 語句。

我的解決方案:

為了異步處理數據,當數據被接收到時,控制器需要指導服務採取什麼行動:

myApp.factory("myFactory", function ($http) {
  return {
    getData: function () {
      return $http.get("/api")
    },
  }
})

myApp.controller("MyController", [
  "$scope",
  "myFactory",
  function ($scope, myFactory) {
    $scope.data = []

    var handleSuccess = function (response, status) {
      $scope.data = response
    }

    myFactory.getData().success(handleSuccess)
  },
])

如果你有任何問題,請讓我知道。😊

使用Express設置代理伺服器

問題:

我正在進行一個使用BreweryDB的項目。在嘗試從API加載一些數據時,我遇到一個問題:該API不支援JSONP。當我試圖直接使用Angular獲取數據時,會導致CORS問題:

XMLHttpRequest無法加載[https://api.brewerydb.com/v2/.](https://api.brewerydb.com/v2/)。請求的資源上沒有'Access-Control-Allow-Origin'頭。因此,不允許“http://localhost:3000”的來源訪問。

我的解決方案:

為了避免暴露我的API密鑰,我需要設置一個中間代理。以下是使用Node.js和Express設置代理的步驟說明。

步驟1:安裝Express和Request

npm install express --save
npm install request --save

步驟2:建立一個 server.js 檔案

var express = require('express');
var request = require('request');
var app = express();

步驟3:設定路由(將 API_KEY 換成你實際的API密鑰)

app.get('/api', function(req, res) {
  request('https://api.brewerydb.com/v2/?key=' + API_KEY, function (error, response, body) {
    if (!error && response.statusCode === 200) {
      console.log(body);
      res.send(body);
    }
  });
});

步驟4:設定埠口

app.listen(3000);
console.log('伺服器在埠口%d運行', 3000);

步驟5:啟動伺服器(node server.js

開啟你的瀏覽器,導航到 http://localhost:3000/api 。你應該能看到JSON物件並且在你的瀏覽器控制台中將其記錄下來:

"message": "請求成功",
"data": "您已到達BreweryDB.com API。對於訪問,請查看http://www.brewerydb.com/developers",
"status": "成功"

如果您遇到任何問題,請隨時向我發送電子郵件。☺

Angular UI Bootstrap:使用ng-repeat開啟第一個手風琴

問題:

我在使用Angular UI Bootstrap版本0.1.2的手風琴指令。在示例頁面上,有一個範例顯示如何默認開啟第一個手風琴組:

<accordion-group heading="First Header" is-open="true"> </accordion-group>

這對於靜態內容來說工作得很好,但是對於使用ng-repeat生成的動態內容來說,它無法如預期地操作。換句話說,它不能這樣工作:

<accordion-group
  heading="{{group.title}}"
  ng-repeat="group in groups"
  is-open="true"
>
</accordion-group>

我的解決方案:

在模板中,將手風琴的is-open屬性綁定如下:

<accordion-group
  heading="{{group.title}}"
  ng-repeat="group in groups"
  is-open="status.isItemOpen[$index]"
>
</accordion-group>

並在控制器中:

$scope.groups = ["First Header", "Second Header", "Third Header"]
$scope.status = {
  isItemOpen: new Array($scope.groups.length),
  isFirstDisabled: false,
}
$scope.status.isItemOpen[0] = true

如果你希望第一個手風琴默認為關閉,則將最後一行的值改為false

如果這個解決方案對你沒有作用,請讓我知道。😊

關於Ionic框架的註解:OS X中的Android平台

在這篇博客文章中,我們將一起研究你在Mac OS X上為Ionic框架的Android平台安裝依賴時可能遇到的幾種錯誤信息。請按照這個官方指南來安裝Cordova和Ionic,然後創建一個項目,直到你配置平台的步驟。

要啟用Android平台,請運行以下命令:

ionic platform add android

然而,你可能遇到這個錯誤:

Error: ANDROID_HOME is not set and "android" command not in your PATH.

步驟1:下載Android SDK

訪問 Android 開發者網站並下載獨立的 SDK 工具:https://developer.android.com/sdk/installing/index.html

步驟2:解壓縮文件

我將SDK解壓縮到我的工作空間的路徑:

/Users/Victor/Workspace/android-sdk-macosx

步驟3:在您的PATH中設置Android命令

注意:將"Victor"替換成您的用戶名。如果您使用的是oh-my-zsh,請將.bash_profile替換成您的.zshrc配置文件。

  1. 打開您的終端並確保 .bash_profile 以一個新行結束:
echo >> /Users/Victor/.bash_profile
  1. .bash_profile中設置 ANDROID_HOME 環境變量:
echo "export ANDROID_HOME=/Users/Victor/Workspace/android-sdk-macosx" >> /Users/Victor/.bash_profile
  1. 也更新PATH變量:
echo "export PATH=${PATH}:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools" >> /Users/Victor/.bash_profile
  1. 重載終端以應用更改:
. /Users/Victor/.bash_profile

步驟4:安裝Android-19

現在,如果您嘗試運行:

ionic platform add android

您可能會看到以下的錯誤:

Error: Please install Android target "android-19".

從命令行運行 android 打開SDK管理器:

android

勾選 Android 4.4.2 (API 19),然後點擊 "Install 8 packages…”。接受授權並等待下載過程完成。

最後,再次嘗試運行命令:

ionic platform add android

然後就成功了:

Project successfully created.

如果您遇到任何問題,請隨時向我發送幫助請求。幹杯!☺

將CircleCI與Karma測試配置

問題

我正在設置使用CircleCI和Karma測試的Angular在Heroku上的持續集成。

![] (./2014-12-22.png)

測試在我的本地主機上可以運行,但在CircleCI上找不到Karma:

噢哦,有些測試沒有通過!
失敗的命令:npm測試
退出代碼:1
輸出:
>啟動 karma karma.conf.js

sh:1:karma:找不到
npm ERR!測試失敗。有關詳細信息,請參見上文。
((npm:test))返回退出代碼1

我的解決方案

要解決這個問題,您可以創建或編輯 circle.yml 配置文件。使用npm添加依賴以全局安裝 karma-cli,並使用Bower安裝Angular,如下所示:

dependencies:
   pre:
     - npm install -g karma-cli bower
     - bower安裝
   cache_directories:
     - ~/nvm

此配置應該可以幫助您在CircleCI上成功運行您的Karma測試。

如何使用Meteor.js上傳檔案?

注意: 本教程使用的是2014年12月15日的Meteor 1.1.3 和 cfs:standard-package 0.0.2。由於此功能正在積極開發中,您閱讀此文時可能已有所變化。如果你有任何疑問,請隨時聯絡我。:)

問題描述

上周,我的一個朋友問我如何在Meteor項目中處理檔案上傳。我建議他使用Collection FS,並按照他們存儲庫的README.md指南。檔案上傳功能在本地主機上工作正常,但一旦部署到免費的Meteor測試服務器,就會失敗。事實上,服務器會不斷刷新,甚至無法加載頁面。

我的解釋

這個問題產生的原因是 FS.filesystem 將圖像上傳到公共資料夾目錄。由於安全考慮,除非經過適當配置,否則服務器不允許這樣做。一個解決方法是使用 GridFS 作為儲存適配器,將圖像插入到MongoDB中。

我的解決方案

安裝

首先,不要使用cfs:filesystem,而要為您的套件使用cfs:gridfs

    meteor add cfs:standard-packages
    meteor add cfs:gridfs
語法

接下來,當聲明您的集合時,從使用 FS.Collection 切換到 FS.Store.GridFS

var imageStore = new FS.Store.GridFS("images")

Images = new FS.Collection("images", {
  stores: [imageStore],
})
權限

然後,根據你的需求設定'deny'和'allow'規則。

Images.deny({
  insert: function () {
    return false
  },
  update:
  created: function () {
    return false
  },
  remove: function () {
    return false
  },
  download: function () {
    return false
  },
})

Images.allow({
  insert: function () {
    return true
  },
  update:
  created: function () {
    return true
  },
  remove: function () {
    return true
  },
  download: function () {
    return true
  },
})
使用者介面

在客戶端模板中添加一個檔案輸入按鈕以供使用者點擊。

<input type="file" name="..." class="myFileInput" />

像這樣處理事件:

Template.Profile.events({
  "change .myFileInput": function (event, template) {
    FS.Utility.eachFile(event, function (file) {
      Images.insert(file, function (err, fileObj) {
        if (err) {
          // handle error
        } else {
          // handle success depending on your needs
          var userId = Meteor.userId()
          var imagesURL = {
            "profile.image": "/cfs/files/images/" + fileObj._id,
          }
          Meteor.users.update(userId, { $set: imagesURL })
        }
      })
    })
  },
})
發佈/訂閱

最後,如果你已經移除了 autopublish 套件,不要忘記設定發佈和訂閱。

Meteor.publish("images", function () {
  return Images.find()
})

在你的 iron:router 中訂閱它:

Router.route("/profile", {
  waitOn: function () {
    return Meteor.subscribe("images")
  },
  action: function () {
    if (this.ready()) this.render("Profile")
    else this.render("Loading")
  },
})

我希望這個解決方案對你有所幫助。如果你正在使用Amazon S3 bucket,可以考慮使用 cfs:s3 作為適配器。如果所有其他方法都失敗了,Filepicker可以作為處理文件上傳的另一種方法。欲了解更多信息,請訪問 Filepicker的網站

與香港General Assembly的問答環節

我被香港General Assembly (GA) 邀請,談論我在Web Development Immersive (WDI) 課程裡的經驗。

1. 自我介紹並描述你目前的項目

我叫Victor,是一名軟件工程師。目前,我正在進行幾個利用JavaScript框架的有趣項目:

  1. 使用Ionic和Neo4j圖形數據庫的原生iOS/Android手機應用程式。
  2. 使用WebRTC,Node.js,和Express.js的視頻聊天室。
  3. 使用WebGL和Three.js的音樂視覺化器。
  4. 使用Angular.js和MongoDB的LinkedIn風格的網絡平台。
  5. 使用Meteor.js和D3數據視覺化的實時投票系統。

其中一些是開源項目。如果你有興趣參與或試用demo,請查看我的GitHub

2. 選擇在GA接受WDI的原因

在參加GA的WDI課程之前,我在澳洲負責社交媒體推廣的數字營銷人員。我的角色激發了我對科技如何迅速改變傳統媒體和市場渠道的興趣。認識到良好網站為數字營銷努力的基石的重要性,我有了開發編碼技能的動力。我選擇在GA接受的WDI而非在香港一所大學夜間上課,是因為我想要一種與最前沿技術保持同步的教育。

3. 回顧學生經驗

我在WDI課程中最喜歡的部分是來自多樣化背景的學生之間的友誼。我們都在技術上和情感上互相幫助。網頁開發是團隊合作,一個網站太複雜,無法完全靠自己建立,無論你的技術水平如何。

4. 課程如何幫助我實現我的目標

我的目標是在這個行業找到工作,GA在香港的強大網絡對此大有幫助。我大量的社交並參與了各種活動,包括黑客馬拉松。對於Justin在這期間的支持表示特別感謝。

5. 課程的前3個經驗

  1. Wireframing:起初,我低估了wireframing的重要性。隨著更多的項目經驗,我已經意識到預先計劃可以長遠節省時間。
  2. 用戶測試:持續的用戶反饋非常重要。代碼應該由市場需求和用戶需求驅動,而不僅僅是由開發人員認為這很酷。
  3. 學習如何學習:課程無法涵蓋所有內容,所以對於持續的發展,自我導向的學習是非常重要的。

6. 過了GA後的生活:接下來是什麼?

我堅守"總是在編碼"的原則。你編碼的越多,你獲得的技能就越好。目前,我正在加強我的理論基礎,以便在IT產業中承擔領導角色。