1f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki/*
2f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki * Copyright (C) 2017 The Android Open Source Project
3f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki *
4f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki * Licensed under the Apache License, Version 2.0 (the "License");
5f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki * you may not use this file except in compliance with the License.
6f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki * You may obtain a copy of the License at
7f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki *
8f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki *      http://www.apache.org/licenses/LICENSE-2.0
9f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki *
10f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki * Unless required by applicable law or agreed to in writing, software
11f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki * distributed under the License is distributed on an "AS IS" BASIS,
12f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki * See the License for the specific language governing permissions and
14f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki * limitations under the License.
15f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki */
16f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
17f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Tokipackage android.view.textclassifier;
18f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
19f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Tokiimport android.annotation.FloatRange;
20f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Tokiimport android.annotation.NonNull;
210d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althausimport android.os.Parcel;
220d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althausimport android.os.Parcelable;
23bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althausimport android.util.ArrayMap;
24f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
25f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Tokiimport com.android.internal.util.Preconditions;
26f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
27f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Tokiimport java.util.ArrayList;
28f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Tokiimport java.util.Collections;
29f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Tokiimport java.util.List;
30f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Tokiimport java.util.Map;
31f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
32f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki/**
33f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki * Helper object for setting and getting entity scores for classified text.
34f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki *
35f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki * @hide
36f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki */
370d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althausfinal class EntityConfidence implements Parcelable {
38f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
390d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    private final ArrayMap<String, Float> mEntityConfidence = new ArrayMap<>();
400d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    private final ArrayList<String> mSortedEntities = new ArrayList<>();
41f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
42f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    EntityConfidence() {}
43f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
440d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    EntityConfidence(@NonNull EntityConfidence source) {
45f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki        Preconditions.checkNotNull(source);
46f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki        mEntityConfidence.putAll(source.mEntityConfidence);
47bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus        mSortedEntities.addAll(source.mSortedEntities);
48f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    }
49f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
50f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    /**
51bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus     * Constructs an EntityConfidence from a map of entity to confidence.
52f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki     *
53bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus     * Map entries that have 0 confidence are removed, and values greater than 1 are clamped to 1.
54bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus     *
55bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus     * @param source a map from entity to a confidence value in the range 0 (low confidence) to
56bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus     *               1 (high confidence).
57f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki     */
580d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    EntityConfidence(@NonNull Map<String, Float> source) {
59bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus        Preconditions.checkNotNull(source);
60bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus
61bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus        // Prune non-existent entities and clamp to 1.
62bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus        mEntityConfidence.ensureCapacity(source.size());
630d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        for (Map.Entry<String, Float> it : source.entrySet()) {
64bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus            if (it.getValue() <= 0) continue;
65bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus            mEntityConfidence.put(it.getKey(), Math.min(1, it.getValue()));
66f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki        }
670d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        resetSortedEntitiesFromMap();
68f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    }
69f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
70f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    /**
71f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki     * Returns an immutable list of entities found in the classified text ordered from
72f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki     * high confidence to low confidence.
73f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki     */
74f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    @NonNull
750d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    public List<String> getEntities() {
76bbe43dfd97c01364e46df452be4c99536d64e4fbJan Althaus        return Collections.unmodifiableList(mSortedEntities);
77f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    }
78f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
79f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    /**
80f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki     * Returns the confidence score for the specified entity. The value ranges from
81f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki     * 0 (low confidence) to 1 (high confidence). 0 indicates that the entity was not found for the
82f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki     * classified text.
83f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki     */
84f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    @FloatRange(from = 0.0, to = 1.0)
850d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    public float getConfidenceScore(String entity) {
86f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki        if (mEntityConfidence.containsKey(entity)) {
87f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki            return mEntityConfidence.get(entity);
88f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki        }
89f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki        return 0;
90f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    }
91f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki
92f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    @Override
93f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    public String toString() {
94f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki        return mEntityConfidence.toString();
95f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki    }
960d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus
970d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    @Override
980d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    public int describeContents() {
990d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        return 0;
1000d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    }
1010d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus
1020d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    @Override
1030d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    public void writeToParcel(Parcel dest, int flags) {
1040d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        dest.writeInt(mEntityConfidence.size());
1050d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        for (Map.Entry<String, Float> entry : mEntityConfidence.entrySet()) {
1060d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus            dest.writeString(entry.getKey());
1070d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus            dest.writeFloat(entry.getValue());
1080d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        }
1090d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    }
1100d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus
1110d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    public static final Parcelable.Creator<EntityConfidence> CREATOR =
1120d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus            new Parcelable.Creator<EntityConfidence>() {
1130d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus                @Override
1140d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus                public EntityConfidence createFromParcel(Parcel in) {
1150d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus                    return new EntityConfidence(in);
1160d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus                }
1170d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus
1180d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus                @Override
1190d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus                public EntityConfidence[] newArray(int size) {
1200d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus                    return new EntityConfidence[size];
1210d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus                }
1220d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus            };
1230d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus
1240d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    private EntityConfidence(Parcel in) {
1250d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        final int numEntities = in.readInt();
1260d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        mEntityConfidence.ensureCapacity(numEntities);
1270d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        for (int i = 0; i < numEntities; ++i) {
1280d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus            mEntityConfidence.put(in.readString(), in.readFloat());
1290d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        }
1300d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        resetSortedEntitiesFromMap();
1310d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    }
1320d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus
1330d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    private void resetSortedEntitiesFromMap() {
1340d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        mSortedEntities.clear();
1350d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        mSortedEntities.ensureCapacity(mEntityConfidence.size());
1360d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        mSortedEntities.addAll(mEntityConfidence.keySet());
1370d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        mSortedEntities.sort((e1, e2) -> {
1380d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus            float score1 = mEntityConfidence.get(e1);
1390d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus            float score2 = mEntityConfidence.get(e2);
1400d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus            return Float.compare(score2, score1);
1410d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus        });
1420d9fbb9bd15fb1c6eae171d316a2de65aaffeb48Jan Althaus    }
143f001fefff3745c29e2ff6903d69ad921df1ea277Abodunrinwa Toki}
144