1use super::*;
7
8pub struct AlgorithmRegistry {
10 config: RegistryConfig,
11 algorithms: HashMap<String, RegisteredAlgorithm>,
12 categories: HashMap<String, Vec<String>>,
13 tags: HashMap<String, HashSet<String>>,
14 search_index: SearchIndex,
15 algorithm_dependencies: HashMap<String, Vec<String>>,
16 algorithm_performance: HashMap<String, AlgorithmPerformanceData>,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct RegisteredAlgorithm {
22 pub algorithm_id: String,
23 pub metadata: AlgorithmMetadata,
24 pub code: AlgorithmCode,
25 pub documentation: AlgorithmDocumentation,
26 pub test_suite: AlgorithmTestSuite,
27 pub performance_benchmarks: Vec<PerformanceBenchmark>,
28 pub licensing: LicensingInfo,
29 pub registration_info: RegistrationInfo,
30 pub usage_statistics: UsageStatistics,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct AlgorithmMetadata {
36 pub name: String,
37 pub version: String,
38 pub description: String,
39 pub author: String,
40 pub author_email: String,
41 pub organization: Option<String>,
42 pub category: AlgorithmCategory,
43 pub subcategory: Option<String>,
44 pub tags: Vec<String>,
45 pub keywords: Vec<String>,
46 pub complexity_class: ComplexityClass,
47 pub quantum_advantage: QuantumAdvantage,
48 pub hardware_requirements: HardwareRequirements,
49 pub dependencies: Vec<Dependency>,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
54pub enum AlgorithmCategory {
55 Optimization,
56 MachineLearning,
57 Cryptography,
58 Simulation,
59 Chemistry,
60 Finance,
61 Logistics,
62 SearchAndDatabase,
63 ErrorCorrection,
64 Characterization,
65 Benchmarking,
66 Utility,
67 Educational,
68 Research,
69 Custom(String),
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct ComplexityClass {
75 pub time_complexity: String,
76 pub space_complexity: String,
77 pub quantum_complexity: String,
78 pub classical_preprocessing: Option<String>,
79 pub classical_postprocessing: Option<String>,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct QuantumAdvantage {
85 pub advantage_type: AdvantageType,
86 pub speedup_factor: Option<f64>,
87 pub problem_size_threshold: Option<usize>,
88 pub verification_method: String,
89 pub theoretical_basis: String,
90 pub experimental_validation: bool,
91}
92
93#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
95pub enum AdvantageType {
96 Exponential,
97 Polynomial,
98 Quadratic,
99 Constant,
100 Unknown,
101 Disputed,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct HardwareRequirements {
107 pub min_qubits: usize,
108 pub recommended_qubits: usize,
109 pub max_circuit_depth: usize,
110 pub required_gates: Vec<String>,
111 pub connectivity_requirements: ConnectivityRequirements,
112 pub fidelity_requirements: FidelityRequirements,
113 pub supported_platforms: Vec<String>,
114 pub special_hardware: Vec<String>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct ConnectivityRequirements {
120 pub topology_type: TopologyType,
121 pub connectivity_degree: Option<usize>,
122 pub all_to_all_required: bool,
123 pub specific_connections: Vec<(usize, usize)>,
124}
125
126#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
128pub enum TopologyType {
129 Linear,
130 Ring,
131 Grid2D,
132 Grid3D,
133 AllToAll,
134 Star,
135 Tree,
136 Random,
137 Custom,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct FidelityRequirements {
143 pub min_gate_fidelity: f64,
144 pub min_readout_fidelity: f64,
145 pub min_state_preparation_fidelity: f64,
146 pub coherence_time_requirement: Duration,
147 pub error_budget: f64,
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct Dependency {
153 pub name: String,
154 pub version: String,
155 pub dependency_type: DependencyType,
156 pub optional: bool,
157 pub purpose: String,
158}
159
160#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
162pub enum DependencyType {
163 QuantumLibrary,
164 ClassicalLibrary,
165 Algorithm,
166 Data,
167 Model,
168 Hardware,
169 Service,
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct AlgorithmCode {
175 pub primary_language: String,
176 pub code_files: Vec<CodeFile>,
177 pub entry_point: String,
178 pub build_instructions: BuildInstructions,
179 pub runtime_requirements: RuntimeRequirements,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct CodeFile {
185 pub filename: String,
186 pub content: String,
187 pub file_type: FileType,
188 pub checksum: String,
189 pub size_bytes: usize,
190}
191
192#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
194pub enum FileType {
195 Source,
196 Header,
197 Configuration,
198 Data,
199 Documentation,
200 Test,
201 Build,
202 Resource,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct BuildInstructions {
208 pub build_system: String,
209 pub build_commands: Vec<String>,
210 pub environment_setup: Vec<String>,
211 pub dependencies_install: Vec<String>,
212 pub validation_commands: Vec<String>,
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct RuntimeRequirements {
218 pub python_version: Option<String>,
219 pub required_packages: Vec<String>,
220 pub environment_variables: HashMap<String, String>,
221 pub resource_constraints: ResourceConstraints,
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct ResourceConstraints {
227 pub max_memory_mb: usize,
228 pub max_cpu_cores: usize,
229 pub max_execution_time_seconds: usize,
230 pub max_quantum_volume: f64,
231 pub max_network_bandwidth_mbps: f64,
232}
233
234#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct AlgorithmDocumentation {
237 pub readme: String,
238 pub api_documentation: String,
239 pub theory_background: String,
240 pub usage_examples: Vec<UsageExample>,
241 pub tutorials: Vec<Tutorial>,
242 pub faq: Vec<FAQEntry>,
243 pub citations: Vec<Citation>,
244 pub changelog: String,
245}
246
247#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct UsageExample {
250 pub title: String,
251 pub description: String,
252 pub code: String,
253 pub expected_output: String,
254 pub complexity: ExampleComplexity,
255}
256
257#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
259pub enum ExampleComplexity {
260 Beginner,
261 Intermediate,
262 Advanced,
263 Expert,
264}
265
266#[derive(Debug, Clone, Serialize, Deserialize)]
268pub struct Tutorial {
269 pub title: String,
270 pub description: String,
271 pub duration_minutes: usize,
272 pub prerequisites: Vec<String>,
273 pub learning_objectives: Vec<String>,
274 pub content: String,
275 pub exercises: Vec<Exercise>,
276}
277
278#[derive(Debug, Clone, Serialize, Deserialize)]
280pub struct Exercise {
281 pub question: String,
282 pub hint: Option<String>,
283 pub solution: String,
284 pub difficulty: ExampleComplexity,
285}
286
287#[derive(Debug, Clone, Serialize, Deserialize)]
289pub struct FAQEntry {
290 pub question: String,
291 pub answer: String,
292 pub category: String,
293 pub votes: i32,
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
298pub struct Citation {
299 pub title: String,
300 pub authors: Vec<String>,
301 pub journal: Option<String>,
302 pub year: u16,
303 pub doi: Option<String>,
304 pub arxiv_id: Option<String>,
305 pub url: Option<String>,
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize)]
310pub struct AlgorithmTestSuite {
311 pub unit_tests: Vec<UnitTest>,
312 pub integration_tests: Vec<IntegrationTest>,
313 pub performance_tests: Vec<PerformanceTest>,
314 pub correctness_tests: Vec<CorrectnessTest>,
315 pub regression_tests: Vec<RegressionTest>,
316 pub coverage_report: CoverageReport,
317}
318
319#[derive(Debug, Clone, Serialize, Deserialize)]
321pub struct UnitTest {
322 pub test_name: String,
323 pub description: String,
324 pub test_code: String,
325 pub expected_result: TestResult,
326 pub timeout_seconds: u32,
327}
328
329#[derive(Debug, Clone, Serialize, Deserialize)]
331pub struct IntegrationTest {
332 pub test_name: String,
333 pub description: String,
334 pub test_scenario: String,
335 pub platforms_tested: Vec<String>,
336 pub expected_behavior: String,
337}
338
339#[derive(Debug, Clone, Serialize, Deserialize)]
341pub struct PerformanceTest {
342 pub test_name: String,
343 pub metrics: Vec<PerformanceMetric>,
344 pub baseline_values: HashMap<String, f64>,
345 pub acceptance_criteria: HashMap<String, f64>,
346}
347
348#[derive(Debug, Clone, Serialize, Deserialize)]
350pub struct PerformanceMetric {
351 pub metric_name: String,
352 pub metric_type: MetricType,
353 pub unit: String,
354 pub description: String,
355}
356
357#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
359pub enum MetricType {
360 ExecutionTime,
361 MemoryUsage,
362 QuantumVolume,
363 CircuitDepth,
364 GateCount,
365 Fidelity,
366 SuccessProbability,
367 ErrorRate,
368 Throughput,
369 Custom(String),
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize)]
374pub struct CorrectnessTest {
375 pub test_name: String,
376 pub input_specification: String,
377 pub expected_output: String,
378 pub verification_method: VerificationMethod,
379 pub tolerance: Option<f64>,
380}
381
382#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
384pub enum VerificationMethod {
385 ExactComparison,
386 NumericalComparison,
387 StatisticalTest,
388 PropertyVerification,
389 CrossValidation,
390 Custom(String),
391}
392
393#[derive(Debug, Clone, Serialize, Deserialize)]
395pub struct RegressionTest {
396 pub test_name: String,
397 pub previous_version: String,
398 pub comparison_metrics: Vec<String>,
399 pub acceptable_regression: f64,
400}
401
402#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
404pub enum TestResult {
405 Pass,
406 Fail,
407 Skip,
408 Error,
409 Timeout,
410}
411
412#[derive(Debug, Clone, Serialize, Deserialize)]
414pub struct CoverageReport {
415 pub line_coverage: f64,
416 pub function_coverage: f64,
417 pub branch_coverage: f64,
418 pub quantum_gate_coverage: f64,
419 pub detailed_report: String,
420}
421
422#[derive(Debug, Clone, Serialize, Deserialize)]
424pub struct PerformanceBenchmark {
425 pub benchmark_id: String,
426 pub platform: String,
427 pub timestamp: SystemTime,
428 pub problem_size: usize,
429 pub metrics: HashMap<String, f64>,
430 pub environment_info: EnvironmentInfo,
431 pub verification_status: VerificationStatus,
432}
433
434#[derive(Debug, Clone, Serialize, Deserialize)]
436pub struct EnvironmentInfo {
437 pub platform_name: String,
438 pub platform_version: String,
439 pub hardware_specs: HashMap<String, String>,
440 pub software_versions: HashMap<String, String>,
441 pub configuration: HashMap<String, String>,
442}
443
444#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
446pub enum VerificationStatus {
447 Verified,
448 Unverified,
449 Failed,
450 Pending,
451}
452
453#[derive(Debug, Clone, Serialize, Deserialize)]
455pub struct LicensingInfo {
456 pub license_type: LicenseType,
457 pub license_text: String,
458 pub commercial_use_allowed: bool,
459 pub attribution_required: bool,
460 pub modification_allowed: bool,
461 pub redistribution_allowed: bool,
462 pub patent_grant: bool,
463 pub copyleft: bool,
464}
465
466#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
468pub enum LicenseType {
469 MIT,
470 Apache2,
471 GPL3,
472 BSD3Clause,
473 Creative,
474 Proprietary,
475 Academic,
476 Custom(String),
477}
478
479#[derive(Debug, Clone, Serialize, Deserialize)]
481pub struct RegistrationInfo {
482 pub registered_at: SystemTime,
483 pub last_updated: SystemTime,
484 pub registration_status: RegistrationStatus,
485 pub review_status: ReviewStatus,
486 pub moderator_notes: Vec<ModeratorNote>,
487 pub verification_badges: Vec<VerificationBadge>,
488}
489
490#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
492pub enum RegistrationStatus {
493 Draft,
494 Submitted,
495 UnderReview,
496 Approved,
497 Rejected,
498 Deprecated,
499 Archived,
500}
501
502#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
504pub enum ReviewStatus {
505 Pending,
506 InProgress,
507 Completed,
508 RequiresChanges,
509 Approved,
510 Rejected,
511}
512
513#[derive(Debug, Clone, Serialize, Deserialize)]
515pub struct ModeratorNote {
516 pub moderator_id: String,
517 pub timestamp: SystemTime,
518 pub note_type: NoteType,
519 pub content: String,
520 pub visibility: NoteVisibility,
521}
522
523#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
525pub enum NoteType {
526 Review,
527 Approval,
528 Rejection,
529 Improvement,
530 Warning,
531 Information,
532}
533
534#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
536pub enum NoteVisibility {
537 Public,
538 AuthorOnly,
539 ModeratorsOnly,
540 Internal,
541}
542
543#[derive(Debug, Clone, Serialize, Deserialize)]
545pub struct VerificationBadge {
546 pub badge_type: BadgeType,
547 pub awarded_by: String,
548 pub awarded_at: SystemTime,
549 pub criteria_met: Vec<String>,
550 pub valid_until: Option<SystemTime>,
551}
552
553#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
555pub enum BadgeType {
556 Verified,
557 HighPerformance,
558 WellDocumented,
559 Tested,
560 Educational,
561 Research,
562 Production,
563 Innovative,
564 Popular,
565 Maintained,
566}
567
568#[derive(Debug, Clone, Serialize, Deserialize)]
570pub struct UsageStatistics {
571 pub total_downloads: u64,
572 pub total_deployments: u64,
573 pub unique_users: u64,
574 pub average_rating: f64,
575 pub total_ratings: u64,
576 pub success_rate: f64,
577 pub last_30_days: UsageStats,
578 pub historical_data: Vec<HistoricalUsage>,
579}
580
581#[derive(Debug, Clone, Serialize, Deserialize)]
583pub struct UsageStats {
584 pub downloads: u64,
585 pub deployments: u64,
586 pub unique_users: u64,
587 pub ratings: u64,
588 pub average_rating: f64,
589}
590
591#[derive(Debug, Clone, Serialize, Deserialize)]
593pub struct HistoricalUsage {
594 pub date: SystemTime,
595 pub stats: UsageStats,
596}
597
598#[derive(Debug, Clone)]
600pub struct SearchIndex {
601 keyword_index: HashMap<String, HashSet<String>>,
602 category_index: HashMap<AlgorithmCategory, HashSet<String>>,
603 tag_index: HashMap<String, HashSet<String>>,
604 author_index: HashMap<String, HashSet<String>>,
605 performance_index: BTreeMap<String, Vec<(String, f64)>>,
606}
607
608#[derive(Debug, Clone)]
610pub struct AlgorithmPerformanceData {
611 pub algorithm_id: String,
612 pub benchmarks: Vec<PerformanceBenchmark>,
613 pub average_performance: HashMap<String, f64>,
614 pub performance_trend: PerformanceTrend,
615 pub comparison_data: HashMap<String, f64>,
616}
617
618#[derive(Debug, Clone)]
620pub struct PerformanceTrend {
621 pub trending_direction: TrendDirection,
622 pub trend_strength: f64,
623 pub last_updated: SystemTime,
624 pub significant_changes: Vec<PerformanceChange>,
625}
626
627#[derive(Debug, Clone, PartialEq)]
629pub enum TrendDirection {
630 Improving,
631 Stable,
632 Declining,
633 Volatile,
634}
635
636#[derive(Debug, Clone)]
638pub struct PerformanceChange {
639 pub metric: String,
640 pub change_percentage: f64,
641 pub change_timestamp: SystemTime,
642 pub context: String,
643}
644
645#[derive(Debug, Clone, Serialize, Deserialize)]
647pub struct AlgorithmRegistration {
648 pub metadata: AlgorithmMetadata,
649 pub code: AlgorithmCode,
650 pub documentation: AlgorithmDocumentation,
651 pub test_suite: AlgorithmTestSuite,
652 pub licensing: LicensingInfo,
653}
654
655impl AlgorithmRegistry {
656 pub fn new(config: &RegistryConfig) -> DeviceResult<Self> {
658 Ok(Self {
659 config: config.clone(),
660 algorithms: HashMap::new(),
661 categories: HashMap::new(),
662 tags: HashMap::new(),
663 search_index: SearchIndex::new(),
664 algorithm_dependencies: HashMap::new(),
665 algorithm_performance: HashMap::new(),
666 })
667 }
668
669 pub async fn initialize(&self) -> DeviceResult<()> {
671 Ok(())
673 }
674
675 pub async fn register_algorithm(
677 &mut self,
678 registration: AlgorithmRegistration,
679 ) -> DeviceResult<String> {
680 let algorithm_id = Uuid::new_v4().to_string();
681
682 let total_size = self.calculate_algorithm_size(®istration.code)?;
684 if total_size > self.config.max_algorithm_size {
685 return Err(DeviceError::InvalidInput(format!(
686 "Algorithm size {} exceeds maximum allowed size {}",
687 total_size, self.config.max_algorithm_size
688 )));
689 }
690
691 if self.algorithms.len() >= self.config.max_algorithms {
693 return Err(DeviceError::ResourceExhaustion(
694 "Maximum number of algorithms reached".to_string(),
695 ));
696 }
697
698 let registered_algorithm = RegisteredAlgorithm {
700 algorithm_id: algorithm_id.clone(),
701 metadata: registration.metadata.clone(),
702 code: registration.code,
703 documentation: registration.documentation,
704 test_suite: registration.test_suite,
705 performance_benchmarks: vec![],
706 licensing: registration.licensing,
707 registration_info: RegistrationInfo {
708 registered_at: SystemTime::now(),
709 last_updated: SystemTime::now(),
710 registration_status: RegistrationStatus::Submitted,
711 review_status: ReviewStatus::Pending,
712 moderator_notes: vec![],
713 verification_badges: vec![],
714 },
715 usage_statistics: UsageStatistics::default(),
716 };
717
718 self.update_search_index(&algorithm_id, ®istration.metadata);
720 self.update_category_index(&algorithm_id, ®istration.metadata.category);
721 self.update_tag_index(&algorithm_id, ®istration.metadata.tags);
722
723 self.algorithms
725 .insert(algorithm_id.clone(), registered_algorithm);
726
727 Ok(algorithm_id)
728 }
729
730 pub async fn get_algorithm(
732 &self,
733 algorithm_id: &str,
734 ) -> DeviceResult<Option<RegisteredAlgorithm>> {
735 Ok(self.algorithms.get(algorithm_id).cloned())
736 }
737
738 pub async fn get_algorithm_count(&self) -> DeviceResult<usize> {
740 Ok(self.algorithms.len())
741 }
742
743 pub async fn search_by_keyword(&self, keyword: &str) -> DeviceResult<Vec<String>> {
745 if let Some(algorithm_ids) = self.search_index.keyword_index.get(keyword) {
746 Ok(algorithm_ids.iter().cloned().collect())
747 } else {
748 Ok(vec![])
749 }
750 }
751
752 pub async fn get_by_category(&self, category: &AlgorithmCategory) -> DeviceResult<Vec<String>> {
754 if let Some(algorithm_ids) = self.search_index.category_index.get(category) {
755 Ok(algorithm_ids.iter().cloned().collect())
756 } else {
757 Ok(vec![])
758 }
759 }
760
761 pub async fn update_performance_data(
763 &mut self,
764 algorithm_id: &str,
765 benchmark: PerformanceBenchmark,
766 ) -> DeviceResult<()> {
767 if let Some(algorithm) = self.algorithms.get_mut(algorithm_id) {
768 algorithm.performance_benchmarks.push(benchmark.clone());
769
770 if let Some(perf_data) = self.algorithm_performance.get_mut(algorithm_id) {
772 perf_data.benchmarks.push(benchmark);
773 } else {
774 let perf_data = AlgorithmPerformanceData {
775 algorithm_id: algorithm_id.to_string(),
776 benchmarks: vec![benchmark],
777 average_performance: HashMap::new(),
778 performance_trend: PerformanceTrend {
779 trending_direction: TrendDirection::Stable,
780 trend_strength: 0.0,
781 last_updated: SystemTime::now(),
782 significant_changes: vec![],
783 },
784 comparison_data: HashMap::new(),
785 };
786 self.algorithm_performance
787 .insert(algorithm_id.to_string(), perf_data);
788 }
789 }
790 Ok(())
791 }
792
793 fn calculate_algorithm_size(&self, code: &AlgorithmCode) -> DeviceResult<usize> {
795 Ok(code.code_files.iter().map(|f| f.size_bytes).sum())
796 }
797
798 fn update_search_index(&mut self, algorithm_id: &str, metadata: &AlgorithmMetadata) {
799 for keyword in &metadata.keywords {
801 self.search_index
802 .keyword_index
803 .entry(keyword.clone())
804 .or_insert_with(HashSet::new)
805 .insert(algorithm_id.to_string());
806 }
807
808 for tag in &metadata.tags {
810 self.search_index
811 .tag_index
812 .entry(tag.clone())
813 .or_insert_with(HashSet::new)
814 .insert(algorithm_id.to_string());
815 }
816
817 self.search_index
819 .author_index
820 .entry(metadata.author.clone())
821 .or_insert_with(HashSet::new)
822 .insert(algorithm_id.to_string());
823 }
824
825 fn update_category_index(&mut self, algorithm_id: &str, category: &AlgorithmCategory) {
826 self.search_index
827 .category_index
828 .entry(category.clone())
829 .or_insert_with(HashSet::new)
830 .insert(algorithm_id.to_string());
831 }
832
833 fn update_tag_index(&mut self, algorithm_id: &str, tags: &[String]) {
834 for tag in tags {
835 self.tags
836 .entry(tag.clone())
837 .or_insert_with(HashSet::new)
838 .insert(algorithm_id.to_string());
839 }
840 }
841}
842
843impl SearchIndex {
844 fn new() -> Self {
845 Self {
846 keyword_index: HashMap::new(),
847 category_index: HashMap::new(),
848 tag_index: HashMap::new(),
849 author_index: HashMap::new(),
850 performance_index: BTreeMap::new(),
851 }
852 }
853}
854
855impl Default for UsageStatistics {
856 fn default() -> Self {
857 Self {
858 total_downloads: 0,
859 total_deployments: 0,
860 unique_users: 0,
861 average_rating: 0.0,
862 total_ratings: 0,
863 success_rate: 0.0,
864 last_30_days: UsageStats::default(),
865 historical_data: vec![],
866 }
867 }
868}
869
870impl Default for UsageStats {
871 fn default() -> Self {
872 Self {
873 downloads: 0,
874 deployments: 0,
875 unique_users: 0,
876 ratings: 0,
877 average_rating: 0.0,
878 }
879 }
880}