71 lines
1.8 KiB
Go
71 lines
1.8 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"strconv"
|
|
|
|
"go-backend-template/internal/client"
|
|
"go-backend-template/internal/contract"
|
|
)
|
|
|
|
type DukcapilService interface {
|
|
FaceMatch(ctx context.Context, req *contract.FaceMatchRequest) (*contract.FaceMatchResponse, error)
|
|
}
|
|
|
|
type DukcapilServiceImpl struct {
|
|
client *client.DukcapilClient
|
|
}
|
|
|
|
func NewDukcapilService(c *client.DukcapilClient) *DukcapilServiceImpl {
|
|
return &DukcapilServiceImpl{client: c}
|
|
}
|
|
|
|
func (s *DukcapilServiceImpl) FaceMatch(ctx context.Context, req *contract.FaceMatchRequest) (*contract.FaceMatchResponse, error) {
|
|
upstream, err := s.client.FaceMatch(ctx, req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
matches := parseFaceMatches(upstream.Response)
|
|
|
|
return &contract.FaceMatchResponse{
|
|
TID: upstream.TID,
|
|
ErrorCode: upstream.ErrorCode,
|
|
Error: upstream.Error,
|
|
RequestType: upstream.RequestType,
|
|
Threshold: upstream.FaceThreshold,
|
|
MaxResults: upstream.MaxResults,
|
|
Matches: matches,
|
|
Raw: upstream,
|
|
}, nil
|
|
}
|
|
|
|
// parseFaceMatches decodes the nested string field
|
|
// `{"face":{"FACE_T5":{"<NIK>":<score>, ...}}}` into a slice of results.
|
|
func parseFaceMatches(raw string) []contract.FaceMatchResult {
|
|
if raw == "" {
|
|
return nil
|
|
}
|
|
var envelope struct {
|
|
Face map[string]map[string]json.Number `json:"face"`
|
|
}
|
|
if err := json.Unmarshal([]byte(raw), &envelope); err != nil {
|
|
return nil
|
|
}
|
|
results := make([]contract.FaceMatchResult, 0)
|
|
for _, group := range envelope.Face {
|
|
for nik, scoreNum := range group {
|
|
score, err := strconv.ParseFloat(scoreNum.String(), 64)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
results = append(results, contract.FaceMatchResult{NIK: nik, Score: score})
|
|
}
|
|
}
|
|
return results
|
|
}
|
|
|
|
// Compile-time assertion.
|
|
var _ DukcapilService = (*DukcapilServiceImpl)(nil)
|