@skan๋์ด ์์ฑํ์ [Q-Bot] ํ์ดํธ๋ฆฌ์คํธ ์ถ์ฒ์ ๋ง๊ฐํฉ๋๋ค. / ๊ฐ์ ์ ์๊ฒฌ ๋ฐ์ต๋๋ค๋ฅผ ๋ณด๊ณ , ์ด๋ป๊ฒ ํ๋ฉด ํฌ์คํ
์ ์ ์ ํ ๊ฐ์น๋ฅผ ๋งค๊ธธ ์ ์์์ง ๊ณ ๋ฏผํด๋ดค์ต๋๋ค.
์ฌ๋๋ง๋ค ์ข์ ๊ธ์ด๋ผ ํ๋จํ๋ ๊ธฐ์ค์ด ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์์นํํ๋ ๊ฒ์ด ๋ถ์ ์ ํ ์ ์๊ฒ ์ง๋ง, ์ด์ ๋ณดํ ๋ด์ ์ฌ์ฉํ ๊ฒ์ด๋ผ๋ฉด ๋ณดํ ๋น์จ์ ์ ํ๊ธฐ ์ํ ๊ธฐ์ค์ ๋ง๋ค์ด ๋ณด๋ ๊ฒ๋ ๊ด์ฐฎ๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์์ต๋๋ค.
์ ๊ฐ ์๊ฐํด ๋ณธ ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌ๊ธ์ ํ์ด์ง ๋ญํฌ ์๊ณ ๋ฆฌ์ฆ์ ์คํ์ ๋ช ์ฑ๋ ์์คํ ์ ์์ด ๋ง๋ Posting Rank ์ ๋๋ค.
์ฐธ๊ณ : ์กฐ์ฑ๋ฌธ๋์ โ์ฝ๊ฒ ์ค๋ช
ํโ ๊ตฌ๊ธ์ ํ์ด์ง ๋ญํฌ ์๊ณ ๋ฆฌ์ฆ
ํ์ด์ง ๋ญํฌ๋ ๊ตฌ๊ธ ๊ฒ์ ์ ์์๊ถ์ ๋
ธ์ถ๋๋ ํ์ด์ง์ ๋ญํน์ ์ ํ๊ธฐ ์ํ ์๊ณ ๋ฆฌ์ฆ ์
๋๋ค.
PR(A) = (1-d)/N + d (PR(T1)/C(T1) + โฆ + PR(Tn)/C(Tn))
PR = ํ์ด์ง ๋ญํฌ
T = ํ์ด์ง
C(T1) = ํ์ด์ง T1์ด ๊ฐ์ง๊ณ ์๋ ๋งํฌ์ ์ด ๊ฐ์
d = Damping Factor๋ผ๋ ์์
N = ๋ชจ๋ ํ์ด์ง์ ์
์คํ์์์ ์๊ฐํด๋ณด๋ฉด
๊ฐ๊ฐ์ ํ์ด์ง๋ @yguhan ๊ฐ์ ๊ณ์ ,
๋งํฌ๋ ๋ฆฌ์คํ,
์ฐํญ์ ๊ฐ์ค์น๋ฅผ ๋ถ๊ณผํ๋ ํ์ด์ง ๋ญํฌ๋ ๊ณ์ ์ ๋ช
์ฑ๋๋ก ์นํํด ๋ณผ ์ ์์ต๋๋ค.
PR(A) = (1-d)/N + d (R(A1)/RC(A1) + ... + R(An)/RC(An))
PR = Posting Rank(ํฌ์คํ
๋ญํฌ)
A = Account(๊ณ์ )
RC(A1) = Resteem Count(A1์ ๋ฆฌ์คํ ํ์)
R = Reputation(๋ช
์ฑ๋)
d = Damping Factor๋ผ๋ ์์
N = ๋ชจ๋ ๊ณ์ ์ ์
๋ฆฌ์คํ์ ์ธ์ฉ ๋งํฌ์ ๋์ํด ๋ณด์๋๋ฐ, ํฌ์คํ ์์ ๋ณดํ < ๋๊ธ << ๋ฆฌ์คํ ์์ผ๋ก ๋ฐ๊ธฐ ์ด๋ ค์์ง๊ธฐ ๋๋ฌธ์ ๋์์ง ์์ ์ ํ์ด๋ผ ์๊ฐํฉ๋๋ค.
๋ชจ๋ ๊ธ์ ๋ฆฌ์คํํ๋ ์ฌ๋๋ณด๋ค ์ด์ฉ๋ค ํ๋ฒ ๋ฆฌ์คํํ๋ ์ฌ๋์ด ๋ฆฌ์คํํ ํฌ์คํ ์ด ๋ ๊ฐ์น๊ฐ ์๋ค๊ณ ๋ณด๊ธฐ์, ๋ถ๋ชจ๋ฅผ ๋ฆฌ์คํ ํ์๋ก ๋๋์ด ์ค๋๋ค. ํ์ง๋ง ์ค๋ ํ๋ํ ์ฌ๋์ ์ด ๋ฆฌ์คํ ํ์๊ฐ ๋ฌด์กฐ๊ฑด ํฌ๊ฒ ๋์ค๊ธฐ ๋๋ฌธ์, 7์ผ๊ฐ ๋ฆฌ์คํํ ํ์๋ก ๋ณด์ ํด์ค๋๋ค.
๋ฌด์กฐ๊ฑด ๋ช ์ฑ๋๊ฐ ๋์ ์ ์ ์ผ์๋ก ์ข์ ๊ธ์ ํ๋ณํ๋ ์๋ชฉ์ด ๋์ ๊ฒ์ด๋ผ ๋งํ๊ธฐ๋ ์ด๋ ต์ง๋ง, ์ค๋ซ๋์ ์คํ์ ์ปค๋ฎค๋ํฐ์์ ํ๋ํด์จ ์ด๋ค์ด ๋ ์ ๋ขฐ๊ฐ ๊ฐ๋ ๊ฒ๋ ์ฌ์ค์ ๋๋ค. ๋ถ๊ณ์ ์ ์ด์ฉํ ๋ฆฌ์คํ๊ฐ์ ์ด๋ทฐ์ง์ ์ต์ ํ๋ ํจ๊ณผ๋ ์๊ณ , ์ ๋ช ๋ฌด์คํ๋ ๋ช ์ฑ๋์ ๊ฐ์น๋ฅผ ์คํํด๋ณผ ์ข์ ๊ธฐํ๋ผ๊ณ ์๊ฐํฉ๋๋ค.
@nand๋์ด ์์ธํ ์ค๋ช
ํด์ฃผ์ [Steem Dictionary] ์คํ์์์ reputation (ํํ,๋ช
์ฑ)์ด๋?์ ์ฝ์ด๋ณด๋ฉด ๋ช
์ฑ๋๊ฐ ๋ก๊ทธ ์ค์ผ์ผ๋ก ์ปค์ง๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ์ด๋ฏธ ์คํ์์ ์ฌ์ฉํด ์จ ๋ง์ ๋ถ๋ค์ ๋ช
์ฑ๋๊ฐ ์ค๋ฅผ ์๋ก +1์ ์ฌ๋ฆฌ๊ธฐ๊ฐ ์ ์ ๋ ์ด๋ ค์์ง๋ค๋ ๊ฒ์ ๋๋ผ์
จ์ ๊ฒ๋๋ค. ์ ์ ์ฌ๋ฆฌ๊ธฐ ์ด๋ ค์์ง๋ ๋ช
์ฑ๋์ ๋์ด๋๋ฅผ ๋ฐ์ํ๊ธฐ ์ํด ๊ฐ์ค์น๋ฅผ reputation์ ์ ๊ณฑ์ผ๋ก ๋ณด์ ํ์ต๋๋ค.
๋ช
์ฑ๋์ ์ํ ์ํฅ๋ ฅ์ 0~1์ฌ์ด์ ์๋ก ๋ง๋ค๊ธฐ ์ํด 10000์ ๋๋ ์ค๋๋ค.
ex) ๋ช
์ฑ๋ 25 -> 25 * 25 / 10000 = 0.0625, ๋ช
์ฑ๋ 70 -> 70 * 70 / 10000 = 0.49
ํฌ์คํ ์ด ๋ฆฌ์คํ ๋ ํ์๊ฐ 0์ด์ฌ๋ ์ต์ 2% ๋ณดํ ์ ๋ณด์ฅํ๊ธฐ ์ํด, (1-d)/N = 0.02๋ก ๊ณ ์ ํฉ๋๋ค.
1, 2, 3, 4๋ฅผ ์ ์ฉํด ๋ง๋ PR์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
PR(A) = 0.02 + 1/10000 * (R(A1)^2/RC(A1) + ... + R(An)^2/RC(An))
PR = Posting Rank(ํฌ์คํ
๋ญํฌ)
A = Account(๊ณ์ )
RC(A1) = Resteem Count(A1์ 7์ผ ๊ฐ ๋ฆฌ์คํ ํ์)
R = Reputation(๋ช
์ฑ๋)
0.02 = ์ต์ ๋ณดํ
๋น์จ(2%)
@asbear๋์ ์น๋ธ๋ผ์ฐ์ ์์ SteemJS๋ก ๊ฐ๋จํ ์คํํ์ ์๋ํ๊ธฐ๋ฅผ ์์ฉํ์ฌ ์น๋ธ๋ผ์ฐ์ ์์ SteemJS๋ก ๊ฐ๋จํ๊ฒ ํฌ์คํ
๋ญํฌ(PostingRank)๋ฅผ ๊ตฌํด๋ด
์๋ค.
ํฌ๋กฌ์์ ์์ฐฝ์ ํ๋ ์ฝ๋๋ค.
์ฐํด๋ฆญ, "๊ฒ์ฌ" ํด๋ฆญ.
"Console" ํด๋ฆญ
์ฝ์์ฐฝ์ SteemJS์ UnderscoreJS๋ฅผ ๋ก๋ฉํฉ๋๋ค.
์๋ ์ฝ๋๋ฅผ ์ฝ์์ฐฝ์ ๋ณต์ฌ ๋ถ์ฌ๋ฃ๊ธฐ ํฉ๋๋ค.
document.write('');
document.write('');
PostingRank๋ฅผ ๊ตฌํด๋ณด๊ณ ์ถ์ ํฌ์คํ
์ ๋งํฌ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
[์ํธํํ ์์ฅ์ ๋ง๋ฒ์ฌ๋ค-๋ฒ์ธํธ] @twinbraid, ๊ทธ๊ฐ ์ ํ๋ ์์ธ ๋งค๋งค(https://steemit.com/kr/@yguhan/twinbraid)
ํฌ์คํ
๋งํฌ์์ ์ ์ yguhan๊ณผ ๋ง์ง๋ง ๋ถ๋ถ์ ์๋ twinbraid๊ฐ ์ฌ์ฉํ ๋ณ์์
๋๋ค.
var author = 'yguhan';
var permlink = 'twinbraid';
์์ ์ฝ๋๋ฅผ ์ด์ ๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ณต์ฌํด์ ์ฝ์์ฐฝ์ ๋ถ์ฌ๋ฃ๊ธฐ ํฉ๋๋ค.
์คํํด๋ณด๊ณ ์ถ์ ํฌ์คํ
์ ๋งํฌ๋ฅผ ๊ฐ์ ธ์์ author์ permlink ๋ถ๋ถ์ ๋ค๋ฅธ ๋ณ์๊ฐ์ ๋ฃ์ด ํ
์คํธ ํด๋ณด์
๋ ์ข์ต๋๋ค.
์์์ ๋ง๋ค์ด๋ณธ PostingRank๋ฅผ ๊ณ์ฐํ๋ ๊ณต์์ ์ฝ๋ํํ์ต๋๋ค.
์ฝ์์ ๋ณต๋ถํด์ ์ถ๋ ฅ๊ฐ์ ํ์ธํด๋ด
์๋ค.
var prPromise = new Promise(function(resolve, reject) {
steem.api.getRebloggedBy(author, permlink, function(err, result){
if (err) return reject(err);
// ๊ธ ์์ฑ์๋ฅผ ์ ์ธํ ๋ฆฌ์คํ ์ ์ ๋ค์ Array
var rebloggers = _.without(result, author);
return resolve(rebloggers);
});
})
.then(function(rebloggers) {
return _.reduce(rebloggers, function(prPromise, reblogger) {
return prPromise.then(function(pr) {
// ๋ช
์ฑ๋ ๊ณ์ฐ
var reputationPromise = new Promise(function(resolve, err) {
steem.api.getAccounts([reblogger], function(err, result) {
if (err) return reject(err);
var reputation = steem.formatter.reputation(result[0].reputation);
return resolve(reputation);
});
});
// RC(Resteem Count) ๊ณ์ฐ
var rcPromise = new Promise(function(resolve, reject) {
steem.api.getState("@" + reblogger, function(err, result) {
if (err) return reject(err);
contents = result.content
var resteemContents = _.pick(contents, function(value, key, object){
// ํด๋น ๊ธ์ ๋ฆฌ์คํํ ์ ์ ์ ๋ธ๋ก๊ทธ์์ ์์ ์ ๊ธ์ด ์๋๊ณ , ์ ์ ๋ณด์์ ๋ฐ์ง ์์ ํฌ์คํ
์ ๊ฐ์
// ์ฆ, 7์ผ ๊ฐ ๋ฆฌ์คํํ ํฌ์คํ
์ ์ด ๊ฐ์๋ฅผ ๊ณ์ฐ
return !new RegExp(reblogger).test(key) && value.author_rewards == 0;
});
rc = _.keys(resteemContents).length;
return resolve(rc);
});
});
// PostingRank๊ฐ ํฉ์ฐ
return Promise.all([reputationPromise, rcPromise]).then(function(results) {
var [reputation, rc] = results;
// ๋ฆฌ์คํ ํ์๊ฐ 0์ด๋ฉด 1๋ก ์ฒ๋ฆฌ
rc = rc !== 0? rc : 1;
// ๋ช
์ฑ๋์ ์ํ ์ํฅ๋ ฅ์ 0~1๋ก ๋ง๋ค๊ธฐ ์ํด 10000๋ฅผ ๋๋
return pr + reputation*reputation/(10000*rc);
});
});
// ๋ฆฌ์คํ ํ์๊ฐ 0์ผ ๋ 2% ๋ณดํ
}, Promise.resolve(0.02));
})
.then(function(pr) {
// posting rank ์ถ๋ ฅ
console.log(pr);
})
.catch(function(err) {
console.log(err);
});
์ต์ข
์ ์ผ๋ก 0.67์ด ์ฐํ์ต๋๋ค.
์ด ๊ฐ์ด PostingRank ๊ฐ์ด๋ฉฐ, ์๊ณ ๋ฆฌ์ฆ์ ์ด ํฌ์คํ
์ ๋ํด 67%์ ๋ณดํ
๋น์จ์ ์ ์ํ์ต๋๋ค.
์์๋ก ์ฌ์ฉํ [์ํธํํ ์์ฅ์ ๋ง๋ฒ์ฌ๋ค-๋ฒ์ธํธ] @twinbraid, ๊ทธ๊ฐ ์ ํ๋ ์์ธ ๋งค๋งค๋ฒ์ 4์ผ ์ ์์ฑํ ๊ธ๋ก ํธ๋ ๋ฉ(๋์ธ๊ธ)์ ์ฌ๋์๊ณ , 8๋ฒ ๋ฆฌ์คํ ๋์์ต๋๋ค.
PostingRank ๊ฐ์ด 1 ์ด์์ธ ๊ฒฝ์ฐ๋ ๊ทนํ ๋๋ฌผ๊ณ ๋๋ถ๋ถ ํธ๋ ๋ฉ(๋์ธ๊ธ)์์ ์ฐพ์๋ณผ ์ ์์์ต๋๋ค. ํ์ง๋ง ๋ชจ๋ ํธ๋ ๋ฉ์ ๊ธ์ด ๋์ PostingRank ๊ฐ์ ์๋ฏธํ์ง๋ ์์ต๋๋ค. ์ ๋ฃ ๋ณดํ ๋ด์ ์ฌ์ฉํ์ฌ ์ธ์์ ์ผ๋ก ๋ณด์์ ๋์ธ ๊ฒฝ์ฐ ๋ฎ์ PostingRank๋ฅผ ๊ธฐ๋กํ์ต๋๋ค.
์ผ์์ ์ธ ๊ธ์ ๋ฆฌ์คํํ๋ ๊ฒฝ์ฐ๋ ์ ๊ธฐ ๋๋ฌธ์ 2% ๋ณดํ ์ด ๋ค์๋ฅผ ์ฐจ์งํ ๊ฒ์ด๋ผ ์์ํ๊ณ , ๋ช๋ช ๋ฆฌ์คํ์ ๋ง์ด ๋์์ง๋ง ๋ณด์ ์์ค์ด ๋ฎ์ ๊ธ์ ๋ฐ๊ฒฌํ๋ ๋ฐ PostingRank๋ฅผ ํ์ฉํด๋ณด๋ฉด ๊ด์ฐฎ๊ฒ ๋ค๋ ์๊ฐ์ด ๋ญ๋๋ค.
@skan๋์ด ๊ณํ์ค์ธ ํ์ดํธ ๋ฆฌ์คํธ ๊ธฐ๋ฐ์ Q-Bot ์ธ์๋
@clayop๋์ด ์งํ์ค์ธ ์๋ชจ์ ํ๊ทธ ์ง์ ๋ด
@virus707๋์ด ์งํ์ค์ธ ์งฑ์งฑ๋งจ ํ๊ทธ ์ง์ ๋ด
๋ค์ด ๋ฌด๋ฃ๋ก KR ์ปค๋ฎค๋ํฐ์์ ํ๋ํ๊ณ ์์ต๋๋ค.
PostingRank๋ ํ๋์ ์์ด๋์ด์ผ ๋ฟ์ด๊ณ , ๋ด ์ด์์ ๋์์ด ๋๋ค๋ฉด ์ข๊ฒ ๋ค์.
SteemJS document๊ฐ ๋ถ์น์ ํด์ ๊ณ ์ํ๋๋ฐ @asbear๋๊ณผ
@morning๋์ด ์ด์ ์ ์ฌ๋ ค์ฃผ์ SteemJS ๊ด๋ จ ํฌ์คํ
์ ๋ณด๊ณ ๋ง์ ๋์์ ๋ฐ์์ต๋๋ค.
๋ ๋ถ๊ป ๊ฐ์ฌ๋๋ฆฝ๋๋ค :)