aifastdb 2.2.6 → 2.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/aifastdb.win32-x64-msvc.node +0 -0
  2. package/dist/carpool/benchmark.d.ts +9 -0
  3. package/dist/carpool/benchmark.d.ts.map +1 -0
  4. package/dist/carpool/benchmark.js +310 -0
  5. package/dist/carpool/benchmark.js.map +1 -0
  6. package/dist/carpool/carpool-credit.d.ts +124 -0
  7. package/dist/carpool/carpool-credit.d.ts.map +1 -0
  8. package/dist/carpool/carpool-credit.js +202 -0
  9. package/dist/carpool/carpool-credit.js.map +1 -0
  10. package/dist/carpool/carpool-index.d.ts +71 -0
  11. package/dist/carpool/carpool-index.d.ts.map +1 -0
  12. package/dist/carpool/carpool-index.js +203 -0
  13. package/dist/carpool/carpool-index.js.map +1 -0
  14. package/dist/carpool/carpool-matcher.d.ts +48 -0
  15. package/dist/carpool/carpool-matcher.d.ts.map +1 -0
  16. package/dist/carpool/carpool-matcher.js +133 -0
  17. package/dist/carpool/carpool-matcher.js.map +1 -0
  18. package/dist/carpool/carpool-matcher.test.d.ts +9 -0
  19. package/dist/carpool/carpool-matcher.test.d.ts.map +1 -0
  20. package/dist/carpool/carpool-matcher.test.js +403 -0
  21. package/dist/carpool/carpool-matcher.test.js.map +1 -0
  22. package/dist/carpool/carpool-privacy.d.ts +72 -0
  23. package/dist/carpool/carpool-privacy.d.ts.map +1 -0
  24. package/dist/carpool/carpool-privacy.js +171 -0
  25. package/dist/carpool/carpool-privacy.js.map +1 -0
  26. package/dist/carpool/carpool-repo.d.ts +175 -0
  27. package/dist/carpool/carpool-repo.d.ts.map +1 -0
  28. package/dist/carpool/carpool-repo.js +698 -0
  29. package/dist/carpool/carpool-repo.js.map +1 -0
  30. package/dist/carpool/carpool-repo.test.d.ts +9 -0
  31. package/dist/carpool/carpool-repo.test.d.ts.map +1 -0
  32. package/dist/carpool/carpool-repo.test.js +452 -0
  33. package/dist/carpool/carpool-repo.test.js.map +1 -0
  34. package/dist/carpool/carpool-scheduler.d.ts +68 -0
  35. package/dist/carpool/carpool-scheduler.d.ts.map +1 -0
  36. package/dist/carpool/carpool-scheduler.js +114 -0
  37. package/dist/carpool/carpool-scheduler.js.map +1 -0
  38. package/dist/carpool/carpool-service.d.ts +105 -0
  39. package/dist/carpool/carpool-service.d.ts.map +1 -0
  40. package/dist/carpool/carpool-service.js +372 -0
  41. package/dist/carpool/carpool-service.js.map +1 -0
  42. package/dist/carpool/carpool-service.test.d.ts +9 -0
  43. package/dist/carpool/carpool-service.test.d.ts.map +1 -0
  44. package/dist/carpool/carpool-service.test.js +455 -0
  45. package/dist/carpool/carpool-service.test.js.map +1 -0
  46. package/dist/carpool/carpool-test.d.ts +11 -0
  47. package/dist/carpool/carpool-test.d.ts.map +1 -0
  48. package/dist/carpool/carpool-test.js +387 -0
  49. package/dist/carpool/carpool-test.js.map +1 -0
  50. package/dist/carpool/index.d.ts +42 -0
  51. package/dist/carpool/index.d.ts.map +1 -0
  52. package/dist/carpool/index.js +80 -0
  53. package/dist/carpool/index.js.map +1 -0
  54. package/dist/carpool/privacy-guard.d.ts +69 -0
  55. package/dist/carpool/privacy-guard.d.ts.map +1 -0
  56. package/dist/carpool/privacy-guard.js +211 -0
  57. package/dist/carpool/privacy-guard.js.map +1 -0
  58. package/dist/carpool/report-system.d.ts +106 -0
  59. package/dist/carpool/report-system.d.ts.map +1 -0
  60. package/dist/carpool/report-system.js +212 -0
  61. package/dist/carpool/report-system.js.map +1 -0
  62. package/dist/carpool/trip-index.d.ts +73 -0
  63. package/dist/carpool/trip-index.d.ts.map +1 -0
  64. package/dist/carpool/trip-index.js +269 -0
  65. package/dist/carpool/trip-index.js.map +1 -0
  66. package/dist/carpool/trip-scheduler.d.ts +71 -0
  67. package/dist/carpool/trip-scheduler.d.ts.map +1 -0
  68. package/dist/carpool/trip-scheduler.js +126 -0
  69. package/dist/carpool/trip-scheduler.js.map +1 -0
  70. package/dist/carpool/trust-evaluator.d.ts +27 -0
  71. package/dist/carpool/trust-evaluator.d.ts.map +1 -0
  72. package/dist/carpool/trust-evaluator.js +117 -0
  73. package/dist/carpool/trust-evaluator.js.map +1 -0
  74. package/dist/carpool/types.d.ts +353 -0
  75. package/dist/carpool/types.d.ts.map +1 -0
  76. package/dist/carpool/types.js +71 -0
  77. package/dist/carpool/types.js.map +1 -0
  78. package/dist/carpool/validators.d.ts +25 -0
  79. package/dist/carpool/validators.d.ts.map +1 -0
  80. package/dist/carpool/validators.js +192 -0
  81. package/dist/carpool/validators.js.map +1 -0
  82. package/dist/carpool/vehicle.test.d.ts +8 -0
  83. package/dist/carpool/vehicle.test.d.ts.map +1 -0
  84. package/dist/carpool/vehicle.test.js +540 -0
  85. package/dist/carpool/vehicle.test.js.map +1 -0
  86. package/dist/index.d.ts +2 -1
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +40 -1
  89. package/dist/index.js.map +1 -1
  90. package/dist/social-graph-v2-vector.test.d.ts +14 -0
  91. package/dist/social-graph-v2-vector.test.d.ts.map +1 -0
  92. package/dist/social-graph-v2-vector.test.js +241 -0
  93. package/dist/social-graph-v2-vector.test.js.map +1 -0
  94. package/dist/social-graph-v2.d.ts +143 -0
  95. package/dist/social-graph-v2.d.ts.map +1 -1
  96. package/dist/social-graph-v2.js +118 -0
  97. package/dist/social-graph-v2.js.map +1 -1
  98. package/dist/social-graph.d.ts.map +1 -1
  99. package/dist/social-graph.js +2 -0
  100. package/dist/social-graph.js.map +1 -1
  101. package/dist/social-types.d.ts +4 -0
  102. package/dist/social-types.d.ts.map +1 -1
  103. package/package.json +3 -1
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ /**
3
+ * Carpool Matcher - Matching Engine
4
+ *
5
+ * 拼车匹配引擎:过滤、评分、排序。
6
+ * 综合社交信任度、历史评分、路线匹配度、发布时间来排序搜索结果。
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.CarpoolMatcher = void 0;
10
+ const DEFAULT_WEIGHTS = {
11
+ trust: 0.4,
12
+ rating: 0.3,
13
+ route: 0.2,
14
+ freshness: 0.1,
15
+ };
16
+ // ============================================================================
17
+ // Matcher Class
18
+ // ============================================================================
19
+ class CarpoolMatcher {
20
+ constructor(weights) {
21
+ this.weights = { ...DEFAULT_WEIGHTS, ...weights };
22
+ }
23
+ /**
24
+ * 计算路线匹配度(0~1)
25
+ *
26
+ * 匹配规则:出发地和目的地各占 50%
27
+ * - 区级匹配:100%
28
+ * - 市级匹配:80%
29
+ * - 省级匹配:60%
30
+ * - 不匹配:0%
31
+ */
32
+ calculateRouteMatch(tripOrigin, tripDest, filterOrigin, filterDest) {
33
+ let originScore = 1.0; // 未指定过滤条件时默认满分
34
+ let destScore = 1.0;
35
+ if (filterOrigin) {
36
+ originScore = this.locationMatch(tripOrigin, filterOrigin);
37
+ }
38
+ if (filterDest) {
39
+ destScore = this.locationMatch(tripDest, filterDest);
40
+ }
41
+ return (originScore + destScore) / 2;
42
+ }
43
+ /**
44
+ * 计算综合匹配分数(0~100)
45
+ */
46
+ calculateMatchScore(trip, trustScore, personRating, filter) {
47
+ const reasons = [];
48
+ // 1. 信任度分 (0~1)
49
+ const trustPart = trustScore.score;
50
+ if (trustScore.level === 'trusted')
51
+ reasons.push('直接好友');
52
+ else if (trustScore.level === 'semi_trusted')
53
+ reasons.push(trustScore.reason);
54
+ else if (trustScore.level === 'known')
55
+ reasons.push(trustScore.reason);
56
+ // 2. 历史评分 (0~1, 归一化 0~5 → 0~1)
57
+ const ratingPart = personRating / 5.0;
58
+ if (personRating >= 4.5)
59
+ reasons.push('好评如潮');
60
+ else if (personRating >= 4.0)
61
+ reasons.push('口碑良好');
62
+ // 3. 路线匹配度 (0~1)
63
+ const filterOrigin = {};
64
+ const filterDest = {};
65
+ if (filter?.origin_province)
66
+ filterOrigin.province = filter.origin_province;
67
+ if (filter?.origin_city)
68
+ filterOrigin.city = filter.origin_city;
69
+ if (filter?.destination_province)
70
+ filterDest.province = filter.destination_province;
71
+ if (filter?.destination_city)
72
+ filterDest.city = filter.destination_city;
73
+ const routePart = this.calculateRouteMatch(trip.properties.origin, trip.properties.destination, Object.keys(filterOrigin).length > 0 ? filterOrigin : undefined, Object.keys(filterDest).length > 0 ? filterDest : undefined);
74
+ if (routePart >= 0.9)
75
+ reasons.push('路线高度吻合');
76
+ else if (routePart >= 0.7)
77
+ reasons.push('路线基本吻合');
78
+ // 4. 新鲜度 (0~1, 7天内线性衰减)
79
+ const ageMs = Date.now() - trip.created_at;
80
+ const ageDays = ageMs / (1000 * 60 * 60 * 24);
81
+ const freshnessPart = Math.max(0, 1 - ageDays / 7);
82
+ if (freshnessPart > 0.8)
83
+ reasons.push('新发布');
84
+ // 综合加权
85
+ const score = (trustPart * this.weights.trust +
86
+ ratingPart * this.weights.rating +
87
+ routePart * this.weights.route +
88
+ freshnessPart * this.weights.freshness) * 100;
89
+ return {
90
+ score: Math.round(Math.min(100, Math.max(0, score)) * 10) / 10,
91
+ reasons,
92
+ };
93
+ }
94
+ /**
95
+ * 对匹配结果排序
96
+ */
97
+ rankResults(results) {
98
+ return results.sort((a, b) => b.match_score - a.match_score);
99
+ }
100
+ // ==========================================================================
101
+ // Internal Helpers
102
+ // ==========================================================================
103
+ /**
104
+ * 计算位置匹配度(0~1)
105
+ */
106
+ locationMatch(actual, filter) {
107
+ // 如果过滤条件中有区级
108
+ if (filter.district && actual.district) {
109
+ if (actual.district === filter.district &&
110
+ actual.city === filter.city &&
111
+ actual.province === filter.province) {
112
+ return 1.0;
113
+ }
114
+ }
115
+ // 市级匹配
116
+ if (filter.city) {
117
+ if (actual.city === filter.city && actual.province === (filter.province ?? actual.province)) {
118
+ return 0.8;
119
+ }
120
+ }
121
+ // 省级匹配
122
+ if (filter.province) {
123
+ if (actual.province === filter.province) {
124
+ return 0.6;
125
+ }
126
+ return 0.0; // 省份不匹配
127
+ }
128
+ // 未指定,默认满分
129
+ return 1.0;
130
+ }
131
+ }
132
+ exports.CarpoolMatcher = CarpoolMatcher;
133
+ //# sourceMappingURL=carpool-matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"carpool-matcher.js","sourceRoot":"","sources":["../../ts/carpool/carpool-matcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CarpoolMatcher & TrustEvaluator - Unit Tests
4
+ *
5
+ * 匹配引擎与社交信任评估的细粒度单元测试。
6
+ * 覆盖路线匹配、综合评分、排序、信任等级计算等。
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=carpool-matcher.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"carpool-matcher.test.d.ts","sourceRoot":"","sources":["../../ts/carpool/carpool-matcher.test.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
@@ -0,0 +1,403 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * CarpoolMatcher & TrustEvaluator - Unit Tests
5
+ *
6
+ * 匹配引擎与社交信任评估的细粒度单元测试。
7
+ * 覆盖路线匹配、综合评分、排序、信任等级计算等。
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ const os = __importStar(require("os"));
44
+ const path = __importStar(require("path"));
45
+ const fs = __importStar(require("fs"));
46
+ const social_graph_v2_1 = require("../social-graph-v2");
47
+ const carpool_matcher_1 = require("./carpool-matcher");
48
+ const trust_evaluator_1 = require("./trust-evaluator");
49
+ const types_1 = require("./types");
50
+ // ============================================================================
51
+ // Test Utilities
52
+ // ============================================================================
53
+ let passed = 0;
54
+ let failed = 0;
55
+ const failures = [];
56
+ function assert(condition, message) {
57
+ if (condition) {
58
+ passed++;
59
+ console.log(` ✅ ${message}`);
60
+ }
61
+ else {
62
+ failed++;
63
+ failures.push(message);
64
+ console.log(` ❌ ${message}`);
65
+ }
66
+ }
67
+ function section(name) {
68
+ console.log(`\n━━━ ${name} ━━━`);
69
+ }
70
+ /** 创建模拟 CarpoolTrip 用于纯逻辑测试 */
71
+ function mockTrip(overrides) {
72
+ const { id = `trip-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`, created_at = Date.now(), ...propOverrides } = overrides ?? {};
73
+ return {
74
+ id,
75
+ name: '测试行程',
76
+ entity_type: types_1.ENTITY_TYPE_CARPOOL_TRIP,
77
+ created_at,
78
+ updated_at: created_at,
79
+ properties: {
80
+ trip_type: 'offer',
81
+ departure_date: '2026-02-20',
82
+ origin: { province: '北京', city: '北京', district: '朝阳区' },
83
+ destination: { province: '河南', city: '漯河' },
84
+ max_passengers: 3,
85
+ current_passengers: 0,
86
+ gender_requirement: 'any',
87
+ price_type: 'share_cost',
88
+ status: 'open',
89
+ ...propOverrides,
90
+ },
91
+ };
92
+ }
93
+ function mockTrustScore(overrides) {
94
+ return {
95
+ score: 0.5,
96
+ level: 'semi_trusted',
97
+ reason: '测试信任',
98
+ mutual_friends_count: 0,
99
+ social_distance: 2,
100
+ ...overrides,
101
+ };
102
+ }
103
+ // ============================================================================
104
+ // CarpoolMatcher Tests
105
+ // ============================================================================
106
+ async function main() {
107
+ console.log('🧪 CarpoolMatcher & TrustEvaluator 单元测试\n');
108
+ // ==========================================================================
109
+ // Part 1: CarpoolMatcher - 路线匹配
110
+ // ==========================================================================
111
+ section('calculateRouteMatch - 区级匹配');
112
+ {
113
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
114
+ const origin = { province: '北京', city: '北京', district: '朝阳区' };
115
+ const dest = { province: '河南', city: '漯河', district: '源汇区' };
116
+ // 完全匹配(区级)
117
+ const score1 = matcher.calculateRouteMatch(origin, dest, { province: '北京', city: '北京', district: '朝阳区' }, { province: '河南', city: '漯河', district: '源汇区' });
118
+ assert(Math.abs(score1 - 1.0) < 0.01, `区级完全匹配: ${score1} ≈ 1.0`);
119
+ }
120
+ section('calculateRouteMatch - 市级匹配');
121
+ {
122
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
123
+ const origin = { province: '北京', city: '北京', district: '朝阳区' };
124
+ const dest = { province: '河南', city: '漯河' };
125
+ const score = matcher.calculateRouteMatch(origin, dest, { province: '北京', city: '北京' }, { province: '河南', city: '漯河' });
126
+ assert(Math.abs(score - 0.8) < 0.01, `市级匹配: ${score} ≈ 0.8`);
127
+ }
128
+ section('calculateRouteMatch - 省级匹配');
129
+ {
130
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
131
+ const origin = { province: '北京', city: '北京' };
132
+ const dest = { province: '河南', city: '漯河' };
133
+ const score = matcher.calculateRouteMatch(origin, dest, { province: '北京' }, { province: '河南' });
134
+ assert(Math.abs(score - 0.6) < 0.01, `省级匹配: ${score} ≈ 0.6`);
135
+ }
136
+ section('calculateRouteMatch - 不匹配');
137
+ {
138
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
139
+ const origin = { province: '北京', city: '北京' };
140
+ const dest = { province: '河南', city: '漯河' };
141
+ const score = matcher.calculateRouteMatch(origin, dest, { province: '上海' }, { province: '广东' });
142
+ assert(Math.abs(score - 0.0) < 0.01, `完全不匹配: ${score} ≈ 0.0`);
143
+ }
144
+ section('calculateRouteMatch - 部分过滤');
145
+ {
146
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
147
+ const origin = { province: '北京', city: '北京' };
148
+ const dest = { province: '河南', city: '漯河' };
149
+ // 只过滤出发地
150
+ const score1 = matcher.calculateRouteMatch(origin, dest, { city: '北京' }, undefined);
151
+ assert(score1 > 0.8, `只过滤出发地: ${score1} > 0.8`);
152
+ // 只过滤目的地
153
+ const score2 = matcher.calculateRouteMatch(origin, dest, undefined, { province: '河南' });
154
+ assert(score2 > 0.7, `只过滤目的地: ${score2} > 0.7`);
155
+ // 不过滤
156
+ const score3 = matcher.calculateRouteMatch(origin, dest, undefined, undefined);
157
+ assert(Math.abs(score3 - 1.0) < 0.01, `无过滤默认满分: ${score3} ≈ 1.0`);
158
+ }
159
+ section('calculateRouteMatch - 出发匹配/目的不匹配');
160
+ {
161
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
162
+ const origin = { province: '北京', city: '北京' };
163
+ const dest = { province: '河南', city: '漯河' };
164
+ const score = matcher.calculateRouteMatch(origin, dest, { province: '北京', city: '北京' }, { province: '广东', city: '广州' });
165
+ // origin: 0.8 (市级), dest: 0.0 (省不匹配) → avg = 0.4
166
+ assert(Math.abs(score - 0.4) < 0.01, `出发匹配+目的不匹配: ${score} ≈ 0.4`);
167
+ }
168
+ // ==========================================================================
169
+ // Part 2: CarpoolMatcher - 综合评分
170
+ // ==========================================================================
171
+ section('calculateMatchScore - 高信任+高评分');
172
+ {
173
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
174
+ const trip = mockTrip();
175
+ const trust = mockTrustScore({ score: 1.0, level: 'trusted' });
176
+ const { score, reasons } = matcher.calculateMatchScore(trip, trust, 5.0, {
177
+ origin_city: '北京',
178
+ destination_province: '河南',
179
+ });
180
+ assert(score > 70, `高信任+高评分: ${score} > 70`);
181
+ assert(reasons.includes('直接好友'), '原因包含 "直接好友"');
182
+ assert(reasons.includes('好评如潮'), '原因包含 "好评如潮"');
183
+ }
184
+ section('calculateMatchScore - 低信任+低评分');
185
+ {
186
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
187
+ const trip = mockTrip({ created_at: Date.now() - 7 * 24 * 60 * 60 * 1000 });
188
+ const trust = mockTrustScore({ score: 0.1, level: 'stranger' });
189
+ const { score, reasons } = matcher.calculateMatchScore(trip, trust, 2.0, {
190
+ origin_city: '上海',
191
+ destination_province: '广东',
192
+ });
193
+ assert(score < 30, `低信任+低评分+不匹配: ${score} < 30`);
194
+ assert(!reasons.includes('直接好友'), '不包含 "直接好友"');
195
+ }
196
+ section('calculateMatchScore - 新鲜度影响');
197
+ {
198
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
199
+ const trust = mockTrustScore({ score: 0.5 });
200
+ // 刚发布
201
+ const freshTrip = mockTrip({ created_at: Date.now() });
202
+ const { score: freshScore } = matcher.calculateMatchScore(freshTrip, trust, 3.0);
203
+ // 7天前发布
204
+ const oldTrip = mockTrip({ created_at: Date.now() - 7 * 24 * 60 * 60 * 1000 });
205
+ const { score: oldScore } = matcher.calculateMatchScore(oldTrip, trust, 3.0);
206
+ assert(freshScore > oldScore, `新行程分(${freshScore}) > 旧行程分(${oldScore})`);
207
+ }
208
+ section('calculateMatchScore - 自定义权重');
209
+ {
210
+ // 完全看信任
211
+ const trustOnlyMatcher = new carpool_matcher_1.CarpoolMatcher({ trust: 1.0, rating: 0, route: 0, freshness: 0 });
212
+ const trip = mockTrip();
213
+ const highTrust = mockTrustScore({ score: 1.0, level: 'trusted' });
214
+ const lowTrust = mockTrustScore({ score: 0.1, level: 'stranger' });
215
+ const { score: highScore } = trustOnlyMatcher.calculateMatchScore(trip, highTrust, 3.0);
216
+ const { score: lowScore } = trustOnlyMatcher.calculateMatchScore(trip, lowTrust, 3.0);
217
+ assert(highScore > lowScore * 5, `纯信任权重: 高(${highScore}) >> 低(${lowScore})`);
218
+ }
219
+ section('calculateMatchScore - 评分4.0~4.5 区间原因');
220
+ {
221
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
222
+ const trip = mockTrip();
223
+ const trust = mockTrustScore({ score: 0.7, level: 'semi_trusted', reason: '2个共同好友' });
224
+ const { reasons: r1 } = matcher.calculateMatchScore(trip, trust, 4.5);
225
+ assert(r1.includes('好评如潮'), '4.5分 → 好评如潮');
226
+ const { reasons: r2 } = matcher.calculateMatchScore(trip, trust, 4.2);
227
+ assert(r2.includes('口碑良好'), '4.2分 → 口碑良好');
228
+ const { reasons: r3 } = matcher.calculateMatchScore(trip, trust, 3.5);
229
+ assert(!r3.includes('好评如潮') && !r3.includes('口碑良好'), '3.5分 → 无评分原因');
230
+ }
231
+ section('calculateMatchScore - 分数范围 0~100');
232
+ {
233
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
234
+ const trip = mockTrip();
235
+ // 最高可能分
236
+ const { score: maxScore } = matcher.calculateMatchScore(trip, mockTrustScore({ score: 1.0 }), 5.0);
237
+ assert(maxScore <= 100, `最高分 ${maxScore} <= 100`);
238
+ assert(maxScore >= 0, `最高分 ${maxScore} >= 0`);
239
+ // 最低可能分
240
+ const { score: minScore } = matcher.calculateMatchScore(mockTrip({ created_at: 0 }), mockTrustScore({ score: 0 }), 0, { origin_city: '不存在' });
241
+ assert(minScore >= 0, `最低分 ${minScore} >= 0`);
242
+ assert(minScore <= 100, `最低分 ${minScore} <= 100`);
243
+ }
244
+ // ==========================================================================
245
+ // Part 3: CarpoolMatcher - 排序
246
+ // ==========================================================================
247
+ section('rankResults');
248
+ {
249
+ const matcher = new carpool_matcher_1.CarpoolMatcher();
250
+ const mockEntity = (name) => ({
251
+ id: name,
252
+ name,
253
+ entity_type: 'person',
254
+ created_at: Date.now(),
255
+ updated_at: Date.now(),
256
+ properties: {},
257
+ });
258
+ const results = [
259
+ {
260
+ trip: mockTrip({ id: 'trip-low' }),
261
+ publisher: mockEntity('P1'),
262
+ match_score: 30,
263
+ match_reasons: [],
264
+ trust_score: mockTrustScore(),
265
+ available_seats: 2,
266
+ },
267
+ {
268
+ trip: mockTrip({ id: 'trip-high' }),
269
+ publisher: mockEntity('P2'),
270
+ match_score: 90,
271
+ match_reasons: [],
272
+ trust_score: mockTrustScore(),
273
+ available_seats: 1,
274
+ },
275
+ {
276
+ trip: mockTrip({ id: 'trip-mid' }),
277
+ publisher: mockEntity('P3'),
278
+ match_score: 60,
279
+ match_reasons: [],
280
+ trust_score: mockTrustScore(),
281
+ available_seats: 3,
282
+ },
283
+ ];
284
+ const ranked = matcher.rankResults(results);
285
+ assert(ranked[0].trip.id === 'trip-high', '排序: 最高分在前');
286
+ assert(ranked[1].trip.id === 'trip-mid', '排序: 中间分在中');
287
+ assert(ranked[2].trip.id === 'trip-low', '排序: 最低分在后');
288
+ }
289
+ // ==========================================================================
290
+ // Part 4: TrustEvaluator
291
+ // ==========================================================================
292
+ const tmpDir = path.join(os.tmpdir(), `carpool-trust-test-${Date.now()}`);
293
+ fs.mkdirSync(tmpDir, { recursive: true });
294
+ const graph = new social_graph_v2_1.SocialGraphV2({ path: tmpDir, shardCount: 2 });
295
+ const trustEval = new trust_evaluator_1.TrustEvaluator(graph);
296
+ // 创建测试人员
297
+ const alice = graph.addPerson({ name: 'Alice' }).id;
298
+ const bob = graph.addPerson({ name: 'Bob' }).id;
299
+ const charlie = graph.addPerson({ name: 'Charlie' }).id;
300
+ const dave = graph.addPerson({ name: 'Dave' }).id;
301
+ const eve = graph.addPerson({ name: 'Eve' }).id;
302
+ const frank = graph.addPerson({ name: 'Frank' }).id;
303
+ section('TrustEvaluator - 同一人');
304
+ {
305
+ const score = trustEval.evaluate(alice, alice);
306
+ assert(score.score === 1.0, '同一人信任分 1.0');
307
+ assert(score.level === 'trusted', '信任等级 trusted');
308
+ assert(score.social_distance === 0, '社交距离 0');
309
+ }
310
+ section('TrustEvaluator - 直接好友');
311
+ {
312
+ graph.addFriend(alice, bob);
313
+ const score = trustEval.evaluate(alice, bob);
314
+ assert(score.score === 1.0, '直接好友信任分 1.0');
315
+ assert(score.level === 'trusted', '信任等级 trusted');
316
+ assert(score.social_distance === 1, '社交距离 1');
317
+ assert(score.reason === '直接好友', '原因: 直接好友');
318
+ }
319
+ section('TrustEvaluator - 同事/同学关系');
320
+ {
321
+ // 用 putRelation 创建 colleague 关系
322
+ graph.putRelation(alice, charlie, 'colleague', 0.8, false);
323
+ const score = trustEval.evaluate(alice, charlie);
324
+ assert(Math.abs(score.score - 0.85) < 0.01, `同事信任分: ${score.score} ≈ 0.85`);
325
+ assert(score.level === 'semi_trusted', '信任等级 semi_trusted');
326
+ assert(score.reason === '同事', '原因: 同事');
327
+ }
328
+ section('TrustEvaluator - knows 关系');
329
+ {
330
+ graph.putRelation(alice, dave, 'knows', 0.5, false);
331
+ const score = trustEval.evaluate(alice, dave);
332
+ assert(Math.abs(score.score - 0.7) < 0.01, `认识关系信任分: ${score.score} ≈ 0.7`);
333
+ assert(score.level === 'semi_trusted', '信任等级 semi_trusted');
334
+ assert(score.reason === '认识的人', '原因: 认识的人');
335
+ }
336
+ section('TrustEvaluator - 共同好友');
337
+ {
338
+ // eve ← 好友 → alice, eve ← 好友 → frank,但 alice 和 frank 没有直接关系
339
+ graph.addFriend(alice, eve);
340
+ graph.addFriend(frank, eve);
341
+ const score = trustEval.evaluate(alice, frank);
342
+ // 有共同好友 eve
343
+ assert(score.score >= 0.7, `共同好友信任分: ${score.score} >= 0.7`);
344
+ assert(score.level === 'semi_trusted' || score.level === 'known', `信任等级: ${score.level}`);
345
+ }
346
+ section('TrustEvaluator - 陌生人');
347
+ {
348
+ const stranger = graph.addPerson({ name: 'Stranger' }).id;
349
+ const score = trustEval.evaluate(alice, stranger);
350
+ assert(score.score <= 0.3, `陌生人信任分: ${score.score} <= 0.3`);
351
+ assert(score.level === 'stranger' || score.level === 'known', `信任等级: ${score.level}`);
352
+ }
353
+ section('TrustEvaluator - evaluateBatch');
354
+ {
355
+ const targets = [bob, charlie, dave];
356
+ const results = trustEval.evaluateBatch(alice, targets);
357
+ assert(results.size === 3, 'evaluateBatch 返回 3 个结果');
358
+ assert(results.has(bob), '包含 Bob');
359
+ assert(results.has(charlie), '包含 Charlie');
360
+ assert(results.has(dave), '包含 Dave');
361
+ // Bob 是直接好友,分数应最高
362
+ const bobScore = results.get(bob);
363
+ const daveScore = results.get(dave);
364
+ assert(bobScore.score >= daveScore.score, 'Bob(好友)信任分 >= Dave(认识)');
365
+ }
366
+ section('TrustEvaluator - 信任等级排序一致性');
367
+ {
368
+ const stranger = graph.addPerson({ name: 'Stranger2' }).id;
369
+ const colleague = graph.addPerson({ name: 'Colleague2' }).id;
370
+ graph.putRelation(alice, colleague, 'colleague', 0.8, false);
371
+ const friendScore = trustEval.evaluate(alice, bob);
372
+ const colleagueScore = trustEval.evaluate(alice, colleague);
373
+ const strangerScore = trustEval.evaluate(alice, stranger);
374
+ assert(friendScore.score >= colleagueScore.score, '好友 >= 同事');
375
+ assert(colleagueScore.score >= strangerScore.score, '同事 >= 陌生人');
376
+ const levelPriority = {
377
+ trusted: 3, semi_trusted: 2, known: 1, stranger: 0,
378
+ };
379
+ assert(levelPriority[friendScore.level] >= levelPriority[colleagueScore.level], '好友等级 >= 同事等级');
380
+ assert(levelPriority[colleagueScore.level] >= levelPriority[strangerScore.level], '同事等级 >= 陌生人等级');
381
+ }
382
+ // ==========================================================================
383
+ // Summary
384
+ // ==========================================================================
385
+ console.log('\n' + '='.repeat(60));
386
+ console.log(`CarpoolMatcher & TrustEvaluator 单元测试完成: ${passed} 通过, ${failed} 失败`);
387
+ if (failures.length > 0) {
388
+ console.log('\n失败用例:');
389
+ failures.forEach(f => console.log(` - ${f}`));
390
+ }
391
+ console.log('='.repeat(60));
392
+ // 清理
393
+ try {
394
+ fs.rmSync(tmpDir, { recursive: true, force: true });
395
+ }
396
+ catch { }
397
+ process.exit(failed > 0 ? 1 : 0);
398
+ }
399
+ main().catch(err => {
400
+ console.error('测试运行失败:', err);
401
+ process.exit(1);
402
+ });
403
+ //# sourceMappingURL=carpool-matcher.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"carpool-matcher.test.js","sourceRoot":"","sources":["../../ts/carpool/carpool-matcher.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Carpool Privacy - Contact Encryption & Visibility Control (T20.3)
3
+ *
4
+ * 隐私安全模块:
5
+ * 1. 联系方式加密存储与脱敏展示
6
+ * 2. 行程可见性控制(公开/好友可见/私密)
7
+ * 3. 基于社交关系的信息访问控制
8
+ */
9
+ import type { SocialGraphV2 } from '../social-graph-v2';
10
+ import type { TripDetail, TrustLevel } from './types';
11
+ /** 行程可见性级别 */
12
+ export type VisibilityLevel = 'public' | 'friends_only' | 'friends_of_friends' | 'private';
13
+ /** 隐私配置 */
14
+ export interface PrivacyConfig {
15
+ /** 加密密钥(用于联系方式加密) */
16
+ encryptionKey?: string;
17
+ /** 默认可见性 */
18
+ defaultVisibility?: VisibilityLevel;
19
+ /** 联系方式展示给哪些信任等级 */
20
+ contactVisibleTo?: TrustLevel[];
21
+ }
22
+ /** 脱敏后的行程详情 */
23
+ export interface SanitizedTripDetail extends Omit<TripDetail, 'trip'> {
24
+ trip: TripDetail['trip'] & {
25
+ /** 联系方式是否可见 */
26
+ contact_visible: boolean;
27
+ };
28
+ }
29
+ export declare class CarpoolPrivacy {
30
+ private graph;
31
+ private config;
32
+ constructor(graph: SocialGraphV2, config?: PrivacyConfig);
33
+ /**
34
+ * 加密联系方式(用于存储)
35
+ *
36
+ * 使用 XOR + Base64 的简单对称加密方案。
37
+ * 生产环境应替换为 AES-256-GCM 等强加密。
38
+ */
39
+ encryptContact(plainText: string): string;
40
+ /**
41
+ * 解密联系方式
42
+ */
43
+ decryptContact(encrypted: string): string;
44
+ /**
45
+ * 手机号脱敏: 138****1234
46
+ */
47
+ maskPhone(phone: string): string;
48
+ /**
49
+ * 微信号脱敏: wx***56
50
+ */
51
+ maskWechat(wechat: string): string;
52
+ /**
53
+ * 通用脱敏
54
+ */
55
+ maskContact(value: string, type?: string): string;
56
+ /**
57
+ * 判断某用户是否可以查看行程的联系方式
58
+ *
59
+ * @param viewerId - 查看者 ID
60
+ * @param publisherId - 发布者 ID
61
+ * @param visibility - 行程可见性级别
62
+ * @returns 是否可见
63
+ */
64
+ canViewContact(viewerId: string, publisherId: string, visibility?: VisibilityLevel): boolean;
65
+ /**
66
+ * 对行程详情进行隐私过滤
67
+ *
68
+ * 根据查看者与发布者的关系,决定是否展示联系方式原文或脱敏版。
69
+ */
70
+ sanitizeTripDetail(detail: TripDetail, viewerId: string, visibility?: VisibilityLevel): SanitizedTripDetail;
71
+ }
72
+ //# sourceMappingURL=carpool-privacy.d.ts.map