vchain_client 1.0.21 → 1.0.22

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 (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/vchain_client.rb +244 -240
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b7db396f9ccc111daf170ae178b5dcc5a7dbe42a
4
- data.tar.gz: 74baca0c18f217d70c2a5b191f89911b9aa13533
3
+ metadata.gz: 65340391974700636c2d48e309226cae1e472797
4
+ data.tar.gz: 132f978b2d7e25377f9efdbc108e4f744a0d74a3
5
5
  SHA512:
6
- metadata.gz: d5043acbd5dbfb6b5848a606404d2e01ce8236c720f666b024adeca956425dd98717b9ec9669c4a991b2c595ab5e42be91efee201faa2c573b469744c143a377
7
- data.tar.gz: 83bfc37f83bc377462189da905466490a444d5f842bbc530bb47d022a23d0e92fcacb085a2ab1e42d4047aa9859f6e32c3835e37ee3f49c8cdb024670c00c71e
6
+ metadata.gz: 110cf09f708a3b23d8de059a9cbb9d14fbfbc48f7dbd4ef7a1f1a3097cb42345fc2b6ed62116fecd60553ad1f2e9a9779914991f0a9bc6602469a6205a4683f1
7
+ data.tar.gz: 959022c40a2975fb038ac62599bcdb320d4101d318fbe82565e3d470770171e8905fd9603356cd6836879b2bd8b717dc09ed90735d1d382967c9bff696bba78c
data/lib/vchain_client.rb CHANGED
@@ -37,10 +37,12 @@ module VChainClient
37
37
 
38
38
  def hash(arr)
39
39
  arr.each { |k, v|
40
- if k != "surname" && k != "given_names"
41
- arr[k] = Digest::SHA512.hexdigest(v.downcase)
42
- else
43
- arr[k] = Digest::SHA512.hexdigest(v)
40
+ if k != "names_parts"
41
+ if k != "surname" && k != "given_names"
42
+ arr[k] = Digest::SHA512.hexdigest(v.downcase)
43
+ else
44
+ arr[k] = Digest::SHA512.hexdigest(v)
45
+ end
44
46
  end
45
47
  }
46
48
  end
@@ -49,10 +51,12 @@ module VChainClient
49
51
  output = {}
50
52
 
51
53
  arr.each { |k, v|
52
- if k != "doc_hash"
53
- output[Digest::SHA512.hexdigest(k)] = Digest::SHA512.hexdigest(v)
54
- else
55
- output[k] = Digest::SHA512.hexdigest(v)
54
+ if k != "names_parts"
55
+ if k != "doc_hash"
56
+ output[Digest::SHA512.hexdigest(k)] = Digest::SHA512.hexdigest(v)
57
+ else
58
+ output[k] = Digest::SHA512.hexdigest(v)
59
+ end
56
60
  end
57
61
  }
58
62
 
@@ -220,7 +224,7 @@ module VChainClient
220
224
  def add_data_point(point_type, input, weight = 1)
221
225
 
222
226
  client_id = @config["client_id"]
223
- api_url = @config["api"]["url"] + "v0.1/addDataPoint/"
227
+ api_url = @config["api"]["url"] + "v0.2/addDataPoint/"
224
228
 
225
229
  time = Time.now.getutc
226
230
  timestamp = time.to_i
@@ -439,7 +443,7 @@ module VChainClient
439
443
 
440
444
  client_id = @config["client_id"]
441
445
 
442
- api_url = @config["api"]["url"] + "v0.1/check/";
446
+ api_url = @config["api"]["url"] + "v0.2/check/";
443
447
 
444
448
  document = input
445
449
 
@@ -455,10 +459,14 @@ module VChainClient
455
459
 
456
460
  document = self.cut(document)
457
461
 
462
+ names_index = {}
463
+
458
464
  if document["type"] == FIELD_TYPE_TRAVEL_DOCUMENT_HASHED
459
465
  document["names"] = []
460
466
  names.each { |name|
461
- document["names"].push(Digest::SHA512.hexdigest(name.downcase))
467
+ name_hash = Digest::SHA512.hexdigest(name.downcase)
468
+ names_index[name_hash] = name
469
+ document["names"].push(name_hash)
462
470
  }
463
471
  end
464
472
 
@@ -528,38 +536,6 @@ module VChainClient
528
536
 
529
537
  # success result
530
538
 
531
- if sent_document.key?("names")
532
-
533
- real_surname = ""
534
-
535
- real_given_name = ""
536
-
537
- if res.key?("names") && res["names"].is_a?(Hash)
538
-
539
- if res["names"].key?("given_names")
540
- sep = "";
541
- res["names"]["given_names"].each { |found_given_name|
542
- real_given_name += sep + found_given_name
543
- sep = " "
544
- }
545
- end
546
-
547
- if res["names"].key?("surname")
548
- sep = "";
549
- res["names"]["surname"].each { |found_surname|
550
- real_surname += sep + found_surname
551
- sep = " "
552
- }
553
- end
554
-
555
- end
556
-
557
- sent_document["given_names"] = Digest::SHA512.hexdigest(real_given_name)
558
- sent_document["surname"] = Digest::SHA512.hexdigest(real_surname)
559
-
560
- sent_document.delete("names")
561
- end
562
-
563
539
  validated_data_points = self.validate_data_points(res["data_points"], res["docs"])
564
540
 
565
541
  if validated_data_points.length == 0
@@ -573,289 +549,317 @@ module VChainClient
573
549
  }
574
550
 
575
551
  return {
576
- "status" => "success",
577
- "validated" => result
552
+ "status" => "success",
553
+ "validated" => result,
554
+ "hashed_input" => sent_document
578
555
  }
579
556
 
580
557
  end
581
558
 
559
+ #
582
560
  # analyse
561
+ #
583
562
 
584
- new_res_docs = []
585
-
586
- res_docs_index = {}
587
-
588
- # cut and index
589
- res["docs"].each { |res_doc|
590
-
591
- full_doc_hash = self.get_doc_hash(res_doc)
592
-
593
- play_doc = {}
594
- res_doc.each { |field, value|
595
- if sent_document.key?(field)
596
- play_doc[field] = value
597
- end
598
- }
599
-
600
- res_doc_credentials_hash = self.get_credentials_hash(play_doc)
601
-
602
- if !res_docs_index.key?(res_doc_credentials_hash)
603
- res_docs_index[res_doc_credentials_hash] = []
604
- end
605
-
606
- play_doc["doc_hash"] = self.get_doc_hash(play_doc)
607
-
608
- play_doc["full_doc_hash"] = full_doc_hash
609
-
610
- res_docs_index[res_doc_credentials_hash].push(play_doc)
611
-
612
- new_res_docs.push(play_doc)
613
- }
614
-
615
- res["docs"] = new_res_docs
616
-
563
+ sent_type_credentials_fields = self.get_credentials_fields(sent_document["type"])
617
564
 
618
- sent_doc_hash = self.get_doc_hash(sent_document)
619
565
 
620
- sent_credentials_hash = self.get_credentials_hash(sent_document)
566
+ # 1. cut non-input fields, rebuild doc_hashes
567
+ # 2. build vectors out of cut documents
621
568
 
622
- hashed_sent_doc = self.full_hash(sent_document)
569
+ cut_res_docs = []
623
570
 
624
- hashed_sent_doc_hash = Digest::SHA512.hexdigest(sent_doc_hash)
571
+ vectors = []
625
572
 
626
- # trying to find exact match by doc_hash
627
-
628
- if validated_data_points.key?(hashed_sent_doc_hash)
629
-
630
- # exact match found by doc_hash
631
-
632
- result = {}
633
-
634
- exact_match = validated_data_points[hashed_sent_doc_hash]
635
-
636
- sent_document.each { |field, value|
637
-
638
- hashed_field = Digest::SHA512.hexdigest(field)
573
+ res["docs"].each { |res_doc|
639
574
 
640
- if exact_match.key?(hashed_field)
575
+ cut_doc = {}
576
+ vector = {}
641
577
 
642
- result[field] = exact_match[hashed_field]
578
+ names_parts = {}
579
+ if res_doc.key?("names_parts")
580
+ names_parts = res_doc["names_parts"]
643
581
 
644
- else
582
+ res_doc.delete("names_parts")
583
+ end
645
584
 
646
- result[field] = 0
585
+ full_doc_hash = self.get_doc_hash(res_doc)
647
586
 
587
+ res_doc.each { |res_doc_field, res_doc_value|
588
+ if sent_document.key?(res_doc_field) || sent_type_credentials_fields.include?(res_doc_field)
589
+ cut_doc[res_doc_field] = res_doc_value
590
+
591
+ vector[Digest::SHA512.hexdigest(res_doc_field)] = [res_doc_value, res_doc_field, 0]
648
592
  end
649
-
650
- }
651
-
652
- return {
653
- "status" => "success",
654
- "validated" => result
655
593
  }
656
594
 
657
- else
658
-
659
- # search by credentials_hash
660
-
661
- found_docs = []
662
- if res_docs_index.key?(sent_credentials_hash)
663
- found_docs = res_docs_index[sent_credentials_hash]
664
- end
665
-
666
- if found_docs.length > 0
595
+ cut_doc["doc_hash"] = self.get_doc_hash(cut_doc)
667
596
 
668
- # matches found by credentials
597
+ cut_doc["full_doc_hash"] = full_doc_hash
669
598
 
670
- result = {}
599
+ hashed_full_doc_hash = Digest::SHA512.hexdigest(full_doc_hash);
671
600
 
672
- possible_mistakes = []
601
+ if validated_data_points.key?(hashed_full_doc_hash)
602
+ data_points = validated_data_points[hashed_full_doc_hash]
673
603
 
674
- cred_fields = self.get_credentials_fields(sent_document["type"]);
604
+ data_points.each { |data_point_field, data_point_value|
605
+ if vector.key?(data_point_field)
606
+ vector[data_point_field][2] += data_point_value
607
+ end
608
+ }
609
+ end
675
610
 
676
- non_cred_fields_index = {}
611
+ if !names_parts.empty?
612
+ cut_doc["names_parts"] = names_parts
613
+ vector["names_parts"] = names_parts
614
+ end
677
615
 
678
- found_docs.each { |cred_doc|
616
+ vectors.push(vector)
679
617
 
680
- cred_doc_hash = cred_doc["full_doc_hash"]#self.get_doc_hash(cred_doc)
681
- cred_doc_hash = Digest::SHA512.hexdigest(cred_doc_hash)
618
+ cut_res_docs.push(cut_doc)
619
+ }
682
620
 
683
- cred_doc_exact_match = validated_data_points[cred_doc_hash]
621
+ res["docs"] = cut_res_docs
684
622
 
685
- # fill credential fields
686
- cred_fields.each { |cred_field|
687
623
 
688
- cred_field_hashed = Digest::SHA512.hexdigest(cred_field)
624
+ # 3. combine vectors part 1 - marking => absorb smaller, merge equal
625
+ for i in 0..(vectors.length - 1)
689
626
 
690
- if !result.key?(cred_field)
691
- result[cred_field] = 0
692
- end
627
+ vector_i = vectors[i]
628
+
629
+ for j in i+1..(vectors.length - 1)
693
630
 
694
- if cred_doc_exact_match.key?(cred_field_hashed)
695
- result[cred_field] += cred_doc_exact_match[cred_field_hashed]
696
- end
631
+ if j >= vectors.length
632
+ break
633
+ end
697
634
 
698
- }
635
+ vector_j = vectors[j]
699
636
 
700
- # fill non credential fields
701
- cred_doc.each { |field, value|
702
-
703
- if !cred_fields.include?(field) && field != "doc_hash"
637
+ i_is_less_j = false
638
+ j_is_less_i = false
704
639
 
705
- non_cred_field_hashed = Digest::SHA512.hexdigest(field)
706
-
707
- if !non_cred_fields_index.key?(field)
708
- non_cred_fields_index[field] = {}
709
- end
640
+ need_to_combine = true
710
641
 
711
- if !non_cred_fields_index[field].key?(value)
712
- non_cred_fields_index[field][value] = 0
642
+ vector_i.each { |vector_i_hashed_field, vector_i_values|
643
+ if vector_i_hashed_field != "names_parts" && vector_i_hashed_field != "resolutions"
644
+ if !vector_j.key?(vector_i_hashed_field)
645
+ j_is_less_i = true
646
+ else
647
+ vector_j_values = vector_j[vector_i_hashed_field]
648
+ if vector_i_values[0] != vector_j_values[0]
649
+ need_to_combine = false
650
+ break
713
651
  end
652
+ end
653
+ end
654
+ }
714
655
 
715
- if cred_doc_exact_match.key?(non_cred_field_hashed)
716
- non_cred_fields_index[field][value] += cred_doc_exact_match[non_cred_field_hashed]
656
+ vector_j.each { |vector_j_hashed_field, vector_j_values|
657
+ if vector_j_hashed_field != "names_parts" && vector_j_hashed_field != "resolutions"
658
+ if !vector_i.key?(vector_j_hashed_field)
659
+ i_is_less_j = true
660
+ else
661
+ vector_i_values = vector_i[vector_j_hashed_field]
662
+ if vector_j_values[0] != vector_i_values[0]
663
+ need_to_combine = false
664
+ break
717
665
  end
718
-
719
666
  end
720
-
721
- }
722
-
667
+ end
723
668
  }
724
669
 
725
- non_cred_fields_index.each { |field, values|
726
-
727
- if sent_document.key?(field)
670
+ if need_to_combine
671
+ if i_is_less_j && j_is_less_i
672
+ # differs, no need to combine
728
673
 
729
- if values.length == 1
674
+ elsif i_is_less_j && !j_is_less_i
675
+ # combine i to j
676
+ if !vectors[i].key?("resolutions")
677
+ vectors[i]["resolutions"] = []
678
+ end
679
+ if !vectors[j].key?("resolutions")
680
+ vectors[j]["resolutions"] = []
681
+ end
682
+ vectors[i]["resolutions"].push(["combine_to", j])
683
+ vectors[j]["resolutions"].push(["absorb", i])
730
684
 
731
- values.take(1).each { |value, validated_count|
732
- if value == sent_document[field]
733
- result[field] = validated_count
734
- else
735
- possible_mistakes.push(field)
736
- end
737
- }
685
+ elsif !i_is_less_j && j_is_less_i
686
+ # combine j to i
687
+ if !vectors[i].key?("resolutions")
688
+ vectors[i]["resolutions"] = []
689
+ end
690
+ if !vectors[j].key?("resolutions")
691
+ vectors[j]["resolutions"] = []
692
+ end
693
+ vectors[j]["resolutions"].push(["combine_to", i])
694
+ vectors[i]["resolutions"].push(["absorb", j])
738
695
 
739
- else
740
- possible_mistakes.push(field)
696
+ else
697
+ # equals, combine j to i and delete j
698
+ if !vectors[i].key?("resolutions")
699
+ vectors[i]["resolutions"] = []
741
700
  end
701
+ if !vectors[j].key?("resolutions")
702
+ vectors[j]["resolutions"] = []
703
+ end
704
+ vectors[j]["resolutions"].push(["combine_to", i])
705
+ vectors[i]["resolutions"].push(["absorb", j])
742
706
 
743
707
  end
708
+ end
709
+ end
710
+ end
744
711
 
745
- }
746
-
747
- return {
748
- "status" => "success",
749
- "possible_mistakes" => possible_mistakes,
750
- "validated" => result
751
- }
752
-
753
- else
754
-
755
- # search for possible errors in credentials
712
+ # 4. combine vectors part 2 - resolutions execution => absorb smaller, merge equal
713
+ vectors_to_remove = []
756
714
 
757
- similar_sets = self.get_similar_credential_sets(sent_document["type"])
715
+ for i in 0..(vectors.length-1)
758
716
 
759
- result = {}
760
- possible_mistakes = []
717
+ vector_i = vectors[i]
761
718
 
762
- other_fields_index = {}
719
+ if vector_i.key?("resolutions")
763
720
 
764
- similar_sets.each { |lookup_set|
721
+ need_to_delete = false
765
722
 
766
- lookup_set_match_found = false
723
+ vector_i["resolutions"].each { |resolution|
724
+
725
+ resolution_type = resolution[0]
767
726
 
768
- res["docs"].each { |res_doc|
727
+ if resolution_type == "combine_to"
728
+
729
+ vector_i["resolutions"].each { |resolution_b|
730
+
731
+ if resolution_b[0] == "absorb"
732
+ if !vectors[resolution[1]].key?("resolutions")
733
+ vectors[resolution[1]]["resolutions"] = []
734
+ end
769
735
 
770
- is_matching = true
736
+ # check for dublicates
737
+ need_to_add = true
771
738
 
772
- lookup_set.each { |lookup_field|
773
- sent_doc_val = sent_document[lookup_field]
774
- res_doc_val = res_doc[lookup_field]
739
+ vectors[resolution[1]]["resolutions"].each { |resolution_c|
740
+ if resolution_c[0] == resolution_b[0] && resolution_c[1] == resolution_b[1]
741
+ need_to_add = false
742
+ break
743
+ end
744
+ }
775
745
 
776
- if sent_doc_val != res_doc_val
777
- is_matching = false
778
- break
746
+ if need_to_add
747
+ vectors[resolution[1]]["resolutions"].push(resolution_b)
748
+ end
779
749
  end
780
750
  }
781
751
 
782
- if is_matching
783
- matching_doc_hash = self.get_doc_hash(res_doc)
784
- matching_doc_hash = Digest::SHA512.hexdigest(matching_doc_hash)
785
-
786
- matching_exact_match = validated_data_points[matching_doc_hash]
787
-
788
- lookup_set.each { |lookup_field|
752
+ need_to_delete = true
753
+ end
754
+ }
789
755
 
790
- lookup_field_hashed = Digest::SHA512.hexdigest(lookup_field)
756
+ if need_to_delete
757
+ vectors_to_remove.push(i)
758
+ end
759
+ end
760
+ end
791
761
 
792
- result[lookup_field] = matching_exact_match[lookup_field_hashed]
793
- }
762
+ for i in 0..(vectors.length - 1)
794
763
 
795
- res_doc.each { |field, value|
796
-
797
- if !lookup_set.include?(field) && field != "doc_hash"
764
+ vector_i = vectors[i]
798
765
 
799
- other_field_hashed = Digest::SHA512.hexdigest(field)
800
-
801
- if !other_fields_index.key?(field)
802
- other_fields_index[field] = {}
803
- end
766
+ if vector_i.key?("resolutions")
767
+ if !vectors_to_remove.include?(i)
804
768
 
805
- if !other_fields_index[field].key?(value)
806
- other_fields_index[field][value] = 0
807
- end
769
+ vector_i["resolutions"].each { |resolution|
808
770
 
809
- if matching_exact_match.key?(other_field_hashed)
810
- other_fields_index[field][value] += matching_exact_match[other_field_hashed]
811
- end
771
+ if resolution[0] == "absorb"
772
+ vector_j = vectors[resolution[1]]
812
773
 
774
+ vector_j.each { |vector_j_hashed_field, vector_j_values|
775
+ if vector_j_hashed_field != "names_parts" && vector_j_hashed_field != "resolutions"
776
+ vectors[i][vector_j_hashed_field][2] += vector_j_values[2]
813
777
  end
814
-
815
778
  }
816
-
817
- lookup_set_match_found = true
818
779
  end
780
+
819
781
  }
820
782
 
821
- if lookup_set_match_found
822
- break
823
- end
783
+ vectors[i].delete("resolutions")
824
784
 
825
- }
785
+ end
786
+ end
787
+ end
826
788
 
827
- other_fields_index.each { |field, values|
789
+ # remove marked vectors
790
+ vectors_removed_number = 0
791
+ vectors_to_remove.each { |index|
792
+ vectors.delete_at(index - vectors_removed_number)
793
+ vectors_removed_number += 1
794
+ }
828
795
 
829
- if sent_document.key?(field)
796
+ # prepare for output
830
797
 
831
- if values.length == 1
798
+ vectors_fliped = []
832
799
 
833
- values.take(1).each { |value, validated_count|
834
- if value == sent_document[field]
835
- result[field] = validated_count
836
- else
837
- possible_mistakes.push(field)
838
- end
839
- }
800
+ for i in 0..(vectors.length - 1)
840
801
 
841
- else
842
- possible_mistakes.push(field)
843
- end
802
+ vector_fliped = {}
844
803
 
845
- end
804
+ vectors[i].each { |hashed_vector_field, vector_values|
846
805
 
847
- }
806
+ if hashed_vector_field != "names_parts"
807
+ val = "same"
808
+ if sent_document[vector_values[1]] != vector_values[0]
809
+ val = "different"
810
+ end
811
+ vector_fliped[vector_values[1]] = [val, vector_values[2]]
812
+ else
813
+ vector_fliped[hashed_vector_field] = vector_values
814
+ end
815
+ }
848
816
 
849
- return {
850
- "status" => "success",
851
- "possible_mistakes" => possible_mistakes,
852
- "validated" => result
853
- }
817
+ vector_raw_surname = ""
818
+ if vector_fliped.key?("names_parts")
819
+ if vector_fliped["names_parts"].key?("surname")
820
+ sep = ""
821
+ vector_fliped["names_parts"]["surname"].each { |surname_part|
822
+ vector_raw_surname += sep + names_index[surname_part]
823
+ sep = " "
824
+ }
825
+ else
826
+ vector_raw_surname = "different"
827
+ end
828
+ else
829
+ vector_raw_surname = "different"
830
+ end
854
831
 
832
+ vector_raw_given_names = ""
833
+ if vector_fliped.key?("names_parts")
834
+ if vector_fliped["names_parts"].key?("given_names")
835
+ sep = ""
836
+ vector_fliped["names_parts"]["given_names"].each { |given_names_part|
837
+ vector_raw_given_names += sep + names_index[given_names_part]
838
+ sep = " "
839
+ }
840
+ else
841
+ vector_raw_given_names = "different"
842
+ end
843
+ else
844
+ vector_raw_given_names = "different"
855
845
  end
856
846
 
847
+ vector_fliped["surname"] = [vector_raw_surname, vector_fliped["surname"][1]]
848
+ vector_fliped["given_names"] = [vector_raw_given_names, vector_fliped["given_names"][1]]
849
+
850
+ vector_fliped.delete("names_parts")
851
+
852
+ vectors_fliped.push(vector_fliped)
853
+
857
854
  end
858
855
 
856
+ # result output
857
+
858
+ return {
859
+ "status" => "success",
860
+ "vectors" => vectors_fliped
861
+ }
862
+
859
863
  end
860
864
  end
861
865
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vchain_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.21
4
+ version: 1.0.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aleksandr Gorelik
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-27 00:00:00.000000000 Z
11
+ date: 2017-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: log4r