丁云鹏 1 年之前
父节点
当前提交
79e17a4998
共有 16 个文件被更改,包括 4492 次插入68 次删除
  1. 44 13
      recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/Feature.java
  2. 101 28
      recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/GetVideoFeatureRequest.java
  3. 8 2
      recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/GetVideoFeatureRequestOrBuilder.java
  4. 877 0
      recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/UserActionFeatureProto.java
  5. 51 0
      recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/UserActionFeatureProtoOrBuilder.java
  6. 1442 0
      recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/UserFeatureProto.java
  7. 120 0
      recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/UserFeatureProtoOrBuilder.java
  8. 1580 0
      recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/VideoFeatureProto.java
  9. 132 0
      recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/VideoFeatureProtoOrBuilder.java
  10. 32 1
      recommend-feature-client/src/main/proto/com/tzld/piaoquan/recommend/feature/feature.proto
  11. 10 1
      recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/model/UserActionFeature.java
  12. 13 0
      recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/model/UserFeature.java
  13. 15 1
      recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/model/VideoFeature.java
  14. 60 0
      recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/service/FeatureConverter.java
  15. 2 10
      recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/service/UserFeatureService.java
  16. 5 12
      recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/service/VideoFeatureService.java

+ 44 - 13
recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/Feature.java

@@ -44,6 +44,11 @@ public final class Feature {
   static final 
     com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
       internal_static_VideoFeatureProto_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_UserActionFeatureProto_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_UserActionFeatureProto_fieldAccessorTable;
 
   public static com.google.protobuf.Descriptors.FileDescriptor
       getDescriptor() {
@@ -59,17 +64,37 @@ public final class Feature {
       "on.proto\"$\n\025GetUserFeatureRequest\022\013\n\003uid" +
       "\030\001 \001(\t\"Z\n\026GetUserFeatureResponse\022\027\n\006resu" +
       "lt\030\001 \001(\0132\007.Result\022\'\n\014user_feature\030\002 \001(\0132" +
-      "\021.UserFeatureProto\"\022\n\020UserFeatureProto\"*" +
-      "\n\026GetVideoFeatureRequest\022\020\n\010video_id\030\001 \001" +
-      "(\003\"]\n\027GetVideoFeatureResponse\022\027\n\006result\030" +
-      "\001 \001(\0132\007.Result\022)\n\rvideo_feature\030\002 \001(\0132\022." +
-      "VideoFeatureProto\"\023\n\021VideoFeatureProto2\231" +
-      "\001\n\016FeatureService\022A\n\016GetUserFeature\022\026.Ge" +
-      "tUserFeatureRequest\032\027.GetUserFeatureResp" +
-      "onse\022D\n\017GetVideoFeature\022\027.GetVideoFeatur" +
-      "eRequest\032\030.GetVideoFeatureResponseB8\n1co" +
-      "m.tzld.piaoquan.recommend.feature.model." +
-      "featureP\001\210\001\001b\006proto3"
+      "\021.UserFeatureProto\"\334\002\n\020UserFeatureProto\022" +
+      "\013\n\003mid\030\001 \001(\t\022\013\n\003uid\030\002 \001(\t\0221\n\020day1_cnt_fe" +
+      "ature\030\003 \001(\0132\027.UserActionFeatureProto\0221\n\020" +
+      "day3_cnt_feature\030\004 \001(\0132\027.UserActionFeatu" +
+      "reProto\0221\n\020day7_cnt_feature\030\005 \001(\0132\027.User" +
+      "ActionFeatureProto\0223\n\022month3_cnt_feature" +
+      "\030\006 \001(\0132\027.UserActionFeatureProto\022\036\n\026user_" +
+      "cycle_bucket_7day\030\007 \001(\t\022\037\n\027user_cycle_bu" +
+      "cket_30day\030\010 \001(\t\022\037\n\027user_share_bucket_30" +
+      "day\030\t \001(\t\"*\n\026GetVideoFeatureRequest\022\020\n\010v" +
+      "ideo_id\030\001 \001(\t\"]\n\027GetVideoFeatureResponse" +
+      "\022\027\n\006result\030\001 \001(\0132\007.Result\022)\n\rvideo_featu" +
+      "re\030\002 \001(\0132\022.VideoFeatureProto\"\354\002\n\021VideoFe" +
+      "atureProto\022\020\n\010video_id\030\001 \001(\t\022\r\n\005up_id\030\002 " +
+      "\001(\t\022\014\n\004tags\030\003 \001(\t\022\023\n\013play_length\030\004 \001(\t\022\022" +
+      "\n\ntotal_time\030\005 \001(\t\022\031\n\021days_since_upload\030" +
+      "\006 \001(\t\0227\n\026video_day1_cnt_feature\030\007 \001(\0132\027." +
+      "UserActionFeatureProto\0227\n\026video_day3_cnt" +
+      "_feature\030\010 \001(\0132\027.UserActionFeatureProto\022" +
+      "7\n\026video_day7_cnt_feature\030\t \001(\0132\027.UserAc" +
+      "tionFeatureProto\0229\n\030video_month3_cnt_fea" +
+      "ture\030\n \001(\0132\027.UserActionFeatureProto\"\212\001\n\026" +
+      "UserActionFeatureProto\022\017\n\007exp_cnt\030\001 \001(\003\022" +
+      "\021\n\tclick_cnt\030\002 \001(\003\022\021\n\tshare_cnt\030\003 \001(\003\022\022\n" +
+      "\nreturn_cnt\030\004 \001(\003\022\013\n\003ctr\030\005 \001(\001\022\013\n\003str\030\006 " +
+      "\001(\001\022\013\n\003rov\030\007 \001(\0012\231\001\n\016FeatureService\022A\n\016G" +
+      "etUserFeature\022\026.GetUserFeatureRequest\032\027." +
+      "GetUserFeatureResponse\022D\n\017GetVideoFeatur" +
+      "e\022\027.GetVideoFeatureRequest\032\030.GetVideoFea" +
+      "tureResponseB8\n1com.tzld.piaoquan.recomm" +
+      "end.feature.model.featureP\001\210\001\001b\006proto3"
     };
     descriptor = com.google.protobuf.Descriptors.FileDescriptor
       .internalBuildGeneratedFileFrom(descriptorData,
@@ -94,7 +119,7 @@ public final class Feature {
     internal_static_UserFeatureProto_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_UserFeatureProto_descriptor,
-        new java.lang.String[] { });
+        new java.lang.String[] { "Mid", "Uid", "Day1CntFeature", "Day3CntFeature", "Day7CntFeature", "Month3CntFeature", "UserCycleBucket7Day", "UserCycleBucket30Day", "UserShareBucket30Day", });
     internal_static_GetVideoFeatureRequest_descriptor =
       getDescriptor().getMessageTypes().get(3);
     internal_static_GetVideoFeatureRequest_fieldAccessorTable = new
@@ -112,7 +137,13 @@ public final class Feature {
     internal_static_VideoFeatureProto_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_VideoFeatureProto_descriptor,
-        new java.lang.String[] { });
+        new java.lang.String[] { "VideoId", "UpId", "Tags", "PlayLength", "TotalTime", "DaysSinceUpload", "VideoDay1CntFeature", "VideoDay3CntFeature", "VideoDay7CntFeature", "VideoMonth3CntFeature", });
+    internal_static_UserActionFeatureProto_descriptor =
+      getDescriptor().getMessageTypes().get(6);
+    internal_static_UserActionFeatureProto_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_UserActionFeatureProto_descriptor,
+        new java.lang.String[] { "ExpCnt", "ClickCnt", "ShareCnt", "ReturnCnt", "Ctr", "Str", "Rov", });
     com.google.protobuf.AnyProto.getDescriptor();
     com.tzld.piaoquan.recommend.feature.model.common.Common.getDescriptor();
   }

+ 101 - 28
recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/GetVideoFeatureRequest.java

@@ -16,6 +16,7 @@ private static final long serialVersionUID = 0L;
     super(builder);
   }
   private GetVideoFeatureRequest() {
+    videoId_ = "";
   }
 
   @java.lang.Override
@@ -48,9 +49,10 @@ private static final long serialVersionUID = 0L;
           case 0:
             done = true;
             break;
-          case 8: {
+          case 10: {
+            java.lang.String s = input.readStringRequireUtf8();
 
-            videoId_ = input.readInt64();
+            videoId_ = s;
             break;
           }
           default: {
@@ -86,14 +88,41 @@ private static final long serialVersionUID = 0L;
   }
 
   public static final int VIDEO_ID_FIELD_NUMBER = 1;
-  private long videoId_;
+  private volatile java.lang.Object videoId_;
   /**
-   * <code>int64 video_id = 1;</code>
+   * <code>string video_id = 1;</code>
    * @return The videoId.
    */
   @java.lang.Override
-  public long getVideoId() {
-    return videoId_;
+  public java.lang.String getVideoId() {
+    java.lang.Object ref = videoId_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      videoId_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string video_id = 1;</code>
+   * @return The bytes for videoId.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getVideoIdBytes() {
+    java.lang.Object ref = videoId_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      videoId_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
   }
 
   private byte memoizedIsInitialized = -1;
@@ -110,8 +139,8 @@ private static final long serialVersionUID = 0L;
   @java.lang.Override
   public void writeTo(com.google.protobuf.CodedOutputStream output)
                       throws java.io.IOException {
-    if (videoId_ != 0L) {
-      output.writeInt64(1, videoId_);
+    if (!getVideoIdBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 1, videoId_);
     }
     unknownFields.writeTo(output);
   }
@@ -122,9 +151,8 @@ private static final long serialVersionUID = 0L;
     if (size != -1) return size;
 
     size = 0;
-    if (videoId_ != 0L) {
-      size += com.google.protobuf.CodedOutputStream
-        .computeInt64Size(1, videoId_);
+    if (!getVideoIdBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, videoId_);
     }
     size += unknownFields.getSerializedSize();
     memoizedSize = size;
@@ -141,8 +169,8 @@ private static final long serialVersionUID = 0L;
     }
     com.tzld.piaoquan.recommend.feature.model.feature.GetVideoFeatureRequest other = (com.tzld.piaoquan.recommend.feature.model.feature.GetVideoFeatureRequest) obj;
 
-    if (getVideoId()
-        != other.getVideoId()) return false;
+    if (!getVideoId()
+        .equals(other.getVideoId())) return false;
     if (!unknownFields.equals(other.unknownFields)) return false;
     return true;
   }
@@ -155,8 +183,7 @@ private static final long serialVersionUID = 0L;
     int hash = 41;
     hash = (19 * hash) + getDescriptor().hashCode();
     hash = (37 * hash) + VIDEO_ID_FIELD_NUMBER;
-    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
-        getVideoId());
+    hash = (53 * hash) + getVideoId().hashCode();
     hash = (29 * hash) + unknownFields.hashCode();
     memoizedHashCode = hash;
     return hash;
@@ -290,7 +317,7 @@ private static final long serialVersionUID = 0L;
     @java.lang.Override
     public Builder clear() {
       super.clear();
-      videoId_ = 0L;
+      videoId_ = "";
 
       return this;
     }
@@ -367,8 +394,9 @@ private static final long serialVersionUID = 0L;
 
     public Builder mergeFrom(com.tzld.piaoquan.recommend.feature.model.feature.GetVideoFeatureRequest other) {
       if (other == com.tzld.piaoquan.recommend.feature.model.feature.GetVideoFeatureRequest.getDefaultInstance()) return this;
-      if (other.getVideoId() != 0L) {
-        setVideoId(other.getVideoId());
+      if (!other.getVideoId().isEmpty()) {
+        videoId_ = other.videoId_;
+        onChanged();
       }
       this.mergeUnknownFields(other.unknownFields);
       onChanged();
@@ -399,33 +427,78 @@ private static final long serialVersionUID = 0L;
       return this;
     }
 
-    private long videoId_ ;
+    private java.lang.Object videoId_ = "";
     /**
-     * <code>int64 video_id = 1;</code>
+     * <code>string video_id = 1;</code>
      * @return The videoId.
      */
-    @java.lang.Override
-    public long getVideoId() {
-      return videoId_;
+    public java.lang.String getVideoId() {
+      java.lang.Object ref = videoId_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        videoId_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
     }
     /**
-     * <code>int64 video_id = 1;</code>
+     * <code>string video_id = 1;</code>
+     * @return The bytes for videoId.
+     */
+    public com.google.protobuf.ByteString
+        getVideoIdBytes() {
+      java.lang.Object ref = videoId_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        videoId_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string video_id = 1;</code>
      * @param value The videoId to set.
      * @return This builder for chaining.
      */
-    public Builder setVideoId(long value) {
-      
+    public Builder setVideoId(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
       videoId_ = value;
       onChanged();
       return this;
     }
     /**
-     * <code>int64 video_id = 1;</code>
+     * <code>string video_id = 1;</code>
      * @return This builder for chaining.
      */
     public Builder clearVideoId() {
       
-      videoId_ = 0L;
+      videoId_ = getDefaultInstance().getVideoId();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string video_id = 1;</code>
+     * @param value The bytes for videoId to set.
+     * @return This builder for chaining.
+     */
+    public Builder setVideoIdBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      videoId_ = value;
       onChanged();
       return this;
     }

+ 8 - 2
recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/GetVideoFeatureRequestOrBuilder.java

@@ -8,8 +8,14 @@ public interface GetVideoFeatureRequestOrBuilder extends
     com.google.protobuf.MessageOrBuilder {
 
   /**
-   * <code>int64 video_id = 1;</code>
+   * <code>string video_id = 1;</code>
    * @return The videoId.
    */
-  long getVideoId();
+  java.lang.String getVideoId();
+  /**
+   * <code>string video_id = 1;</code>
+   * @return The bytes for videoId.
+   */
+  com.google.protobuf.ByteString
+      getVideoIdBytes();
 }

+ 877 - 0
recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/UserActionFeatureProto.java

@@ -0,0 +1,877 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/feature/feature.proto
+
+package com.tzld.piaoquan.recommend.feature.model.feature;
+
+/**
+ * Protobuf type {@code UserActionFeatureProto}
+ */
+public final class UserActionFeatureProto extends
+    com.google.protobuf.GeneratedMessageV3 implements
+    // @@protoc_insertion_point(message_implements:UserActionFeatureProto)
+    UserActionFeatureProtoOrBuilder {
+private static final long serialVersionUID = 0L;
+  // Use UserActionFeatureProto.newBuilder() to construct.
+  private UserActionFeatureProto(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    super(builder);
+  }
+  private UserActionFeatureProto() {
+  }
+
+  @java.lang.Override
+  @SuppressWarnings({"unused"})
+  protected java.lang.Object newInstance(
+      UnusedPrivateParameter unused) {
+    return new UserActionFeatureProto();
+  }
+
+  @java.lang.Override
+  public final com.google.protobuf.UnknownFieldSet
+  getUnknownFields() {
+    return this.unknownFields;
+  }
+  private UserActionFeatureProto(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    this();
+    if (extensionRegistry == null) {
+      throw new java.lang.NullPointerException();
+    }
+    com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+        com.google.protobuf.UnknownFieldSet.newBuilder();
+    try {
+      boolean done = false;
+      while (!done) {
+        int tag = input.readTag();
+        switch (tag) {
+          case 0:
+            done = true;
+            break;
+          case 8: {
+
+            expCnt_ = input.readInt64();
+            break;
+          }
+          case 16: {
+
+            clickCnt_ = input.readInt64();
+            break;
+          }
+          case 24: {
+
+            shareCnt_ = input.readInt64();
+            break;
+          }
+          case 32: {
+
+            returnCnt_ = input.readInt64();
+            break;
+          }
+          case 41: {
+
+            ctr_ = input.readDouble();
+            break;
+          }
+          case 49: {
+
+            str_ = input.readDouble();
+            break;
+          }
+          case 57: {
+
+            rov_ = input.readDouble();
+            break;
+          }
+          default: {
+            if (!parseUnknownField(
+                input, unknownFields, extensionRegistry, tag)) {
+              done = true;
+            }
+            break;
+          }
+        }
+      }
+    } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+      throw e.setUnfinishedMessage(this);
+    } catch (java.io.IOException e) {
+      throw new com.google.protobuf.InvalidProtocolBufferException(
+          e).setUnfinishedMessage(this);
+    } finally {
+      this.unknownFields = unknownFields.build();
+      makeExtensionsImmutable();
+    }
+  }
+  public static final com.google.protobuf.Descriptors.Descriptor
+      getDescriptor() {
+    return com.tzld.piaoquan.recommend.feature.model.feature.Feature.internal_static_UserActionFeatureProto_descriptor;
+  }
+
+  @java.lang.Override
+  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internalGetFieldAccessorTable() {
+    return com.tzld.piaoquan.recommend.feature.model.feature.Feature.internal_static_UserActionFeatureProto_fieldAccessorTable
+        .ensureFieldAccessorsInitialized(
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.class, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder.class);
+  }
+
+  public static final int EXP_CNT_FIELD_NUMBER = 1;
+  private long expCnt_;
+  /**
+   * <code>int64 exp_cnt = 1;</code>
+   * @return The expCnt.
+   */
+  @java.lang.Override
+  public long getExpCnt() {
+    return expCnt_;
+  }
+
+  public static final int CLICK_CNT_FIELD_NUMBER = 2;
+  private long clickCnt_;
+  /**
+   * <code>int64 click_cnt = 2;</code>
+   * @return The clickCnt.
+   */
+  @java.lang.Override
+  public long getClickCnt() {
+    return clickCnt_;
+  }
+
+  public static final int SHARE_CNT_FIELD_NUMBER = 3;
+  private long shareCnt_;
+  /**
+   * <code>int64 share_cnt = 3;</code>
+   * @return The shareCnt.
+   */
+  @java.lang.Override
+  public long getShareCnt() {
+    return shareCnt_;
+  }
+
+  public static final int RETURN_CNT_FIELD_NUMBER = 4;
+  private long returnCnt_;
+  /**
+   * <code>int64 return_cnt = 4;</code>
+   * @return The returnCnt.
+   */
+  @java.lang.Override
+  public long getReturnCnt() {
+    return returnCnt_;
+  }
+
+  public static final int CTR_FIELD_NUMBER = 5;
+  private double ctr_;
+  /**
+   * <code>double ctr = 5;</code>
+   * @return The ctr.
+   */
+  @java.lang.Override
+  public double getCtr() {
+    return ctr_;
+  }
+
+  public static final int STR_FIELD_NUMBER = 6;
+  private double str_;
+  /**
+   * <code>double str = 6;</code>
+   * @return The str.
+   */
+  @java.lang.Override
+  public double getStr() {
+    return str_;
+  }
+
+  public static final int ROV_FIELD_NUMBER = 7;
+  private double rov_;
+  /**
+   * <code>double rov = 7;</code>
+   * @return The rov.
+   */
+  @java.lang.Override
+  public double getRov() {
+    return rov_;
+  }
+
+  private byte memoizedIsInitialized = -1;
+  @java.lang.Override
+  public final boolean isInitialized() {
+    byte isInitialized = memoizedIsInitialized;
+    if (isInitialized == 1) return true;
+    if (isInitialized == 0) return false;
+
+    memoizedIsInitialized = 1;
+    return true;
+  }
+
+  @java.lang.Override
+  public void writeTo(com.google.protobuf.CodedOutputStream output)
+                      throws java.io.IOException {
+    if (expCnt_ != 0L) {
+      output.writeInt64(1, expCnt_);
+    }
+    if (clickCnt_ != 0L) {
+      output.writeInt64(2, clickCnt_);
+    }
+    if (shareCnt_ != 0L) {
+      output.writeInt64(3, shareCnt_);
+    }
+    if (returnCnt_ != 0L) {
+      output.writeInt64(4, returnCnt_);
+    }
+    if (ctr_ != 0D) {
+      output.writeDouble(5, ctr_);
+    }
+    if (str_ != 0D) {
+      output.writeDouble(6, str_);
+    }
+    if (rov_ != 0D) {
+      output.writeDouble(7, rov_);
+    }
+    unknownFields.writeTo(output);
+  }
+
+  @java.lang.Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    size = 0;
+    if (expCnt_ != 0L) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt64Size(1, expCnt_);
+    }
+    if (clickCnt_ != 0L) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt64Size(2, clickCnt_);
+    }
+    if (shareCnt_ != 0L) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt64Size(3, shareCnt_);
+    }
+    if (returnCnt_ != 0L) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt64Size(4, returnCnt_);
+    }
+    if (ctr_ != 0D) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeDoubleSize(5, ctr_);
+    }
+    if (str_ != 0D) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeDoubleSize(6, str_);
+    }
+    if (rov_ != 0D) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeDoubleSize(7, rov_);
+    }
+    size += unknownFields.getSerializedSize();
+    memoizedSize = size;
+    return size;
+  }
+
+  @java.lang.Override
+  public boolean equals(final java.lang.Object obj) {
+    if (obj == this) {
+     return true;
+    }
+    if (!(obj instanceof com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto)) {
+      return super.equals(obj);
+    }
+    com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto other = (com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto) obj;
+
+    if (getExpCnt()
+        != other.getExpCnt()) return false;
+    if (getClickCnt()
+        != other.getClickCnt()) return false;
+    if (getShareCnt()
+        != other.getShareCnt()) return false;
+    if (getReturnCnt()
+        != other.getReturnCnt()) return false;
+    if (java.lang.Double.doubleToLongBits(getCtr())
+        != java.lang.Double.doubleToLongBits(
+            other.getCtr())) return false;
+    if (java.lang.Double.doubleToLongBits(getStr())
+        != java.lang.Double.doubleToLongBits(
+            other.getStr())) return false;
+    if (java.lang.Double.doubleToLongBits(getRov())
+        != java.lang.Double.doubleToLongBits(
+            other.getRov())) return false;
+    if (!unknownFields.equals(other.unknownFields)) return false;
+    return true;
+  }
+
+  @java.lang.Override
+  public int hashCode() {
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
+    }
+    int hash = 41;
+    hash = (19 * hash) + getDescriptor().hashCode();
+    hash = (37 * hash) + EXP_CNT_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        getExpCnt());
+    hash = (37 * hash) + CLICK_CNT_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        getClickCnt());
+    hash = (37 * hash) + SHARE_CNT_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        getShareCnt());
+    hash = (37 * hash) + RETURN_CNT_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        getReturnCnt());
+    hash = (37 * hash) + CTR_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        java.lang.Double.doubleToLongBits(getCtr()));
+    hash = (37 * hash) + STR_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        java.lang.Double.doubleToLongBits(getStr()));
+    hash = (37 * hash) + ROV_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        java.lang.Double.doubleToLongBits(getRov()));
+    hash = (29 * hash) + unknownFields.hashCode();
+    memoizedHashCode = hash;
+    return hash;
+  }
+
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseFrom(
+      java.nio.ByteBuffer data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseFrom(
+      java.nio.ByteBuffer data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseFrom(
+      com.google.protobuf.ByteString data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseFrom(
+      com.google.protobuf.ByteString data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseFrom(byte[] data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseFrom(
+      byte[] data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseDelimitedFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseDelimitedFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseFrom(
+      com.google.protobuf.CodedInputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parseFrom(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  @java.lang.Override
+  public Builder newBuilderForType() { return newBuilder(); }
+  public static Builder newBuilder() {
+    return DEFAULT_INSTANCE.toBuilder();
+  }
+  public static Builder newBuilder(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto prototype) {
+    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+  }
+  @java.lang.Override
+  public Builder toBuilder() {
+    return this == DEFAULT_INSTANCE
+        ? new Builder() : new Builder().mergeFrom(this);
+  }
+
+  @java.lang.Override
+  protected Builder newBuilderForType(
+      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+    Builder builder = new Builder(parent);
+    return builder;
+  }
+  /**
+   * Protobuf type {@code UserActionFeatureProto}
+   */
+  public static final class Builder extends
+      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+      // @@protoc_insertion_point(builder_implements:UserActionFeatureProto)
+      com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder {
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.tzld.piaoquan.recommend.feature.model.feature.Feature.internal_static_UserActionFeatureProto_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.tzld.piaoquan.recommend.feature.model.feature.Feature.internal_static_UserActionFeatureProto_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.class, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder.class);
+    }
+
+    // Construct using com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.newBuilder()
+    private Builder() {
+      maybeForceBuilderInitialization();
+    }
+
+    private Builder(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      super(parent);
+      maybeForceBuilderInitialization();
+    }
+    private void maybeForceBuilderInitialization() {
+      if (com.google.protobuf.GeneratedMessageV3
+              .alwaysUseFieldBuilders) {
+      }
+    }
+    @java.lang.Override
+    public Builder clear() {
+      super.clear();
+      expCnt_ = 0L;
+
+      clickCnt_ = 0L;
+
+      shareCnt_ = 0L;
+
+      returnCnt_ = 0L;
+
+      ctr_ = 0D;
+
+      str_ = 0D;
+
+      rov_ = 0D;
+
+      return this;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.Descriptor
+        getDescriptorForType() {
+      return com.tzld.piaoquan.recommend.feature.model.feature.Feature.internal_static_UserActionFeatureProto_descriptor;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDefaultInstanceForType() {
+      return com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance();
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto build() {
+      com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto buildPartial() {
+      com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto result = new com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto(this);
+      result.expCnt_ = expCnt_;
+      result.clickCnt_ = clickCnt_;
+      result.shareCnt_ = shareCnt_;
+      result.returnCnt_ = returnCnt_;
+      result.ctr_ = ctr_;
+      result.str_ = str_;
+      result.rov_ = rov_;
+      onBuilt();
+      return result;
+    }
+
+    @java.lang.Override
+    public Builder clone() {
+      return super.clone();
+    }
+    @java.lang.Override
+    public Builder setField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.setField(field, value);
+    }
+    @java.lang.Override
+    public Builder clearField(
+        com.google.protobuf.Descriptors.FieldDescriptor field) {
+      return super.clearField(field);
+    }
+    @java.lang.Override
+    public Builder clearOneof(
+        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+      return super.clearOneof(oneof);
+    }
+    @java.lang.Override
+    public Builder setRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        int index, java.lang.Object value) {
+      return super.setRepeatedField(field, index, value);
+    }
+    @java.lang.Override
+    public Builder addRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.addRepeatedField(field, value);
+    }
+    @java.lang.Override
+    public Builder mergeFrom(com.google.protobuf.Message other) {
+      if (other instanceof com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto) {
+        return mergeFrom((com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto)other);
+      } else {
+        super.mergeFrom(other);
+        return this;
+      }
+    }
+
+    public Builder mergeFrom(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto other) {
+      if (other == com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance()) return this;
+      if (other.getExpCnt() != 0L) {
+        setExpCnt(other.getExpCnt());
+      }
+      if (other.getClickCnt() != 0L) {
+        setClickCnt(other.getClickCnt());
+      }
+      if (other.getShareCnt() != 0L) {
+        setShareCnt(other.getShareCnt());
+      }
+      if (other.getReturnCnt() != 0L) {
+        setReturnCnt(other.getReturnCnt());
+      }
+      if (other.getCtr() != 0D) {
+        setCtr(other.getCtr());
+      }
+      if (other.getStr() != 0D) {
+        setStr(other.getStr());
+      }
+      if (other.getRov() != 0D) {
+        setRov(other.getRov());
+      }
+      this.mergeUnknownFields(other.unknownFields);
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      return true;
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto parsedMessage = null;
+      try {
+        parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        parsedMessage = (com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto) e.getUnfinishedMessage();
+        throw e.unwrapIOException();
+      } finally {
+        if (parsedMessage != null) {
+          mergeFrom(parsedMessage);
+        }
+      }
+      return this;
+    }
+
+    private long expCnt_ ;
+    /**
+     * <code>int64 exp_cnt = 1;</code>
+     * @return The expCnt.
+     */
+    @java.lang.Override
+    public long getExpCnt() {
+      return expCnt_;
+    }
+    /**
+     * <code>int64 exp_cnt = 1;</code>
+     * @param value The expCnt to set.
+     * @return This builder for chaining.
+     */
+    public Builder setExpCnt(long value) {
+      
+      expCnt_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int64 exp_cnt = 1;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearExpCnt() {
+      
+      expCnt_ = 0L;
+      onChanged();
+      return this;
+    }
+
+    private long clickCnt_ ;
+    /**
+     * <code>int64 click_cnt = 2;</code>
+     * @return The clickCnt.
+     */
+    @java.lang.Override
+    public long getClickCnt() {
+      return clickCnt_;
+    }
+    /**
+     * <code>int64 click_cnt = 2;</code>
+     * @param value The clickCnt to set.
+     * @return This builder for chaining.
+     */
+    public Builder setClickCnt(long value) {
+      
+      clickCnt_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int64 click_cnt = 2;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearClickCnt() {
+      
+      clickCnt_ = 0L;
+      onChanged();
+      return this;
+    }
+
+    private long shareCnt_ ;
+    /**
+     * <code>int64 share_cnt = 3;</code>
+     * @return The shareCnt.
+     */
+    @java.lang.Override
+    public long getShareCnt() {
+      return shareCnt_;
+    }
+    /**
+     * <code>int64 share_cnt = 3;</code>
+     * @param value The shareCnt to set.
+     * @return This builder for chaining.
+     */
+    public Builder setShareCnt(long value) {
+      
+      shareCnt_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int64 share_cnt = 3;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearShareCnt() {
+      
+      shareCnt_ = 0L;
+      onChanged();
+      return this;
+    }
+
+    private long returnCnt_ ;
+    /**
+     * <code>int64 return_cnt = 4;</code>
+     * @return The returnCnt.
+     */
+    @java.lang.Override
+    public long getReturnCnt() {
+      return returnCnt_;
+    }
+    /**
+     * <code>int64 return_cnt = 4;</code>
+     * @param value The returnCnt to set.
+     * @return This builder for chaining.
+     */
+    public Builder setReturnCnt(long value) {
+      
+      returnCnt_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int64 return_cnt = 4;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearReturnCnt() {
+      
+      returnCnt_ = 0L;
+      onChanged();
+      return this;
+    }
+
+    private double ctr_ ;
+    /**
+     * <code>double ctr = 5;</code>
+     * @return The ctr.
+     */
+    @java.lang.Override
+    public double getCtr() {
+      return ctr_;
+    }
+    /**
+     * <code>double ctr = 5;</code>
+     * @param value The ctr to set.
+     * @return This builder for chaining.
+     */
+    public Builder setCtr(double value) {
+      
+      ctr_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>double ctr = 5;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearCtr() {
+      
+      ctr_ = 0D;
+      onChanged();
+      return this;
+    }
+
+    private double str_ ;
+    /**
+     * <code>double str = 6;</code>
+     * @return The str.
+     */
+    @java.lang.Override
+    public double getStr() {
+      return str_;
+    }
+    /**
+     * <code>double str = 6;</code>
+     * @param value The str to set.
+     * @return This builder for chaining.
+     */
+    public Builder setStr(double value) {
+      
+      str_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>double str = 6;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearStr() {
+      
+      str_ = 0D;
+      onChanged();
+      return this;
+    }
+
+    private double rov_ ;
+    /**
+     * <code>double rov = 7;</code>
+     * @return The rov.
+     */
+    @java.lang.Override
+    public double getRov() {
+      return rov_;
+    }
+    /**
+     * <code>double rov = 7;</code>
+     * @param value The rov to set.
+     * @return This builder for chaining.
+     */
+    public Builder setRov(double value) {
+      
+      rov_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>double rov = 7;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearRov() {
+      
+      rov_ = 0D;
+      onChanged();
+      return this;
+    }
+    @java.lang.Override
+    public final Builder setUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.setUnknownFields(unknownFields);
+    }
+
+    @java.lang.Override
+    public final Builder mergeUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.mergeUnknownFields(unknownFields);
+    }
+
+
+    // @@protoc_insertion_point(builder_scope:UserActionFeatureProto)
+  }
+
+  // @@protoc_insertion_point(class_scope:UserActionFeatureProto)
+  private static final com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto DEFAULT_INSTANCE;
+  static {
+    DEFAULT_INSTANCE = new com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto();
+  }
+
+  public static com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+
+  private static final com.google.protobuf.Parser<UserActionFeatureProto>
+      PARSER = new com.google.protobuf.AbstractParser<UserActionFeatureProto>() {
+    @java.lang.Override
+    public UserActionFeatureProto parsePartialFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return new UserActionFeatureProto(input, extensionRegistry);
+    }
+  };
+
+  public static com.google.protobuf.Parser<UserActionFeatureProto> parser() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.protobuf.Parser<UserActionFeatureProto> getParserForType() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDefaultInstanceForType() {
+    return DEFAULT_INSTANCE;
+  }
+
+}
+

+ 51 - 0
recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/UserActionFeatureProtoOrBuilder.java

@@ -0,0 +1,51 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/feature/feature.proto
+
+package com.tzld.piaoquan.recommend.feature.model.feature;
+
+public interface UserActionFeatureProtoOrBuilder extends
+    // @@protoc_insertion_point(interface_extends:UserActionFeatureProto)
+    com.google.protobuf.MessageOrBuilder {
+
+  /**
+   * <code>int64 exp_cnt = 1;</code>
+   * @return The expCnt.
+   */
+  long getExpCnt();
+
+  /**
+   * <code>int64 click_cnt = 2;</code>
+   * @return The clickCnt.
+   */
+  long getClickCnt();
+
+  /**
+   * <code>int64 share_cnt = 3;</code>
+   * @return The shareCnt.
+   */
+  long getShareCnt();
+
+  /**
+   * <code>int64 return_cnt = 4;</code>
+   * @return The returnCnt.
+   */
+  long getReturnCnt();
+
+  /**
+   * <code>double ctr = 5;</code>
+   * @return The ctr.
+   */
+  double getCtr();
+
+  /**
+   * <code>double str = 6;</code>
+   * @return The str.
+   */
+  double getStr();
+
+  /**
+   * <code>double rov = 7;</code>
+   * @return The rov.
+   */
+  double getRov();
+}

+ 1442 - 0
recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/UserFeatureProto.java

@@ -16,6 +16,11 @@ private static final long serialVersionUID = 0L;
     super(builder);
   }
   private UserFeatureProto() {
+    mid_ = "";
+    uid_ = "";
+    userCycleBucket7Day_ = "";
+    userCycleBucket30Day_ = "";
+    userShareBucket30Day_ = "";
   }
 
   @java.lang.Override
@@ -48,6 +53,88 @@ private static final long serialVersionUID = 0L;
           case 0:
             done = true;
             break;
+          case 10: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            mid_ = s;
+            break;
+          }
+          case 18: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            uid_ = s;
+            break;
+          }
+          case 26: {
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder subBuilder = null;
+            if (day1CntFeature_ != null) {
+              subBuilder = day1CntFeature_.toBuilder();
+            }
+            day1CntFeature_ = input.readMessage(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.parser(), extensionRegistry);
+            if (subBuilder != null) {
+              subBuilder.mergeFrom(day1CntFeature_);
+              day1CntFeature_ = subBuilder.buildPartial();
+            }
+
+            break;
+          }
+          case 34: {
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder subBuilder = null;
+            if (day3CntFeature_ != null) {
+              subBuilder = day3CntFeature_.toBuilder();
+            }
+            day3CntFeature_ = input.readMessage(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.parser(), extensionRegistry);
+            if (subBuilder != null) {
+              subBuilder.mergeFrom(day3CntFeature_);
+              day3CntFeature_ = subBuilder.buildPartial();
+            }
+
+            break;
+          }
+          case 42: {
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder subBuilder = null;
+            if (day7CntFeature_ != null) {
+              subBuilder = day7CntFeature_.toBuilder();
+            }
+            day7CntFeature_ = input.readMessage(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.parser(), extensionRegistry);
+            if (subBuilder != null) {
+              subBuilder.mergeFrom(day7CntFeature_);
+              day7CntFeature_ = subBuilder.buildPartial();
+            }
+
+            break;
+          }
+          case 50: {
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder subBuilder = null;
+            if (month3CntFeature_ != null) {
+              subBuilder = month3CntFeature_.toBuilder();
+            }
+            month3CntFeature_ = input.readMessage(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.parser(), extensionRegistry);
+            if (subBuilder != null) {
+              subBuilder.mergeFrom(month3CntFeature_);
+              month3CntFeature_ = subBuilder.buildPartial();
+            }
+
+            break;
+          }
+          case 58: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            userCycleBucket7Day_ = s;
+            break;
+          }
+          case 66: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            userCycleBucket30Day_ = s;
+            break;
+          }
+          case 74: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            userShareBucket30Day_ = s;
+            break;
+          }
           default: {
             if (!parseUnknownField(
                 input, unknownFields, extensionRegistry, tag)) {
@@ -80,6 +167,300 @@ private static final long serialVersionUID = 0L;
             com.tzld.piaoquan.recommend.feature.model.feature.UserFeatureProto.class, com.tzld.piaoquan.recommend.feature.model.feature.UserFeatureProto.Builder.class);
   }
 
+  public static final int MID_FIELD_NUMBER = 1;
+  private volatile java.lang.Object mid_;
+  /**
+   * <code>string mid = 1;</code>
+   * @return The mid.
+   */
+  @java.lang.Override
+  public java.lang.String getMid() {
+    java.lang.Object ref = mid_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      mid_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string mid = 1;</code>
+   * @return The bytes for mid.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getMidBytes() {
+    java.lang.Object ref = mid_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      mid_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int UID_FIELD_NUMBER = 2;
+  private volatile java.lang.Object uid_;
+  /**
+   * <code>string uid = 2;</code>
+   * @return The uid.
+   */
+  @java.lang.Override
+  public java.lang.String getUid() {
+    java.lang.Object ref = uid_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      uid_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string uid = 2;</code>
+   * @return The bytes for uid.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getUidBytes() {
+    java.lang.Object ref = uid_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      uid_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int DAY1_CNT_FEATURE_FIELD_NUMBER = 3;
+  private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto day1CntFeature_;
+  /**
+   * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+   * @return Whether the day1CntFeature field is set.
+   */
+  @java.lang.Override
+  public boolean hasDay1CntFeature() {
+    return day1CntFeature_ != null;
+  }
+  /**
+   * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+   * @return The day1CntFeature.
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDay1CntFeature() {
+    return day1CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : day1CntFeature_;
+  }
+  /**
+   * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getDay1CntFeatureOrBuilder() {
+    return getDay1CntFeature();
+  }
+
+  public static final int DAY3_CNT_FEATURE_FIELD_NUMBER = 4;
+  private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto day3CntFeature_;
+  /**
+   * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+   * @return Whether the day3CntFeature field is set.
+   */
+  @java.lang.Override
+  public boolean hasDay3CntFeature() {
+    return day3CntFeature_ != null;
+  }
+  /**
+   * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+   * @return The day3CntFeature.
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDay3CntFeature() {
+    return day3CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : day3CntFeature_;
+  }
+  /**
+   * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getDay3CntFeatureOrBuilder() {
+    return getDay3CntFeature();
+  }
+
+  public static final int DAY7_CNT_FEATURE_FIELD_NUMBER = 5;
+  private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto day7CntFeature_;
+  /**
+   * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+   * @return Whether the day7CntFeature field is set.
+   */
+  @java.lang.Override
+  public boolean hasDay7CntFeature() {
+    return day7CntFeature_ != null;
+  }
+  /**
+   * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+   * @return The day7CntFeature.
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDay7CntFeature() {
+    return day7CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : day7CntFeature_;
+  }
+  /**
+   * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getDay7CntFeatureOrBuilder() {
+    return getDay7CntFeature();
+  }
+
+  public static final int MONTH3_CNT_FEATURE_FIELD_NUMBER = 6;
+  private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto month3CntFeature_;
+  /**
+   * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+   * @return Whether the month3CntFeature field is set.
+   */
+  @java.lang.Override
+  public boolean hasMonth3CntFeature() {
+    return month3CntFeature_ != null;
+  }
+  /**
+   * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+   * @return The month3CntFeature.
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getMonth3CntFeature() {
+    return month3CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : month3CntFeature_;
+  }
+  /**
+   * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getMonth3CntFeatureOrBuilder() {
+    return getMonth3CntFeature();
+  }
+
+  public static final int USER_CYCLE_BUCKET_7DAY_FIELD_NUMBER = 7;
+  private volatile java.lang.Object userCycleBucket7Day_;
+  /**
+   * <code>string user_cycle_bucket_7day = 7;</code>
+   * @return The userCycleBucket7day.
+   */
+  @java.lang.Override
+  public java.lang.String getUserCycleBucket7Day() {
+    java.lang.Object ref = userCycleBucket7Day_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      userCycleBucket7Day_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string user_cycle_bucket_7day = 7;</code>
+   * @return The bytes for userCycleBucket7day.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getUserCycleBucket7DayBytes() {
+    java.lang.Object ref = userCycleBucket7Day_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      userCycleBucket7Day_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int USER_CYCLE_BUCKET_30DAY_FIELD_NUMBER = 8;
+  private volatile java.lang.Object userCycleBucket30Day_;
+  /**
+   * <code>string user_cycle_bucket_30day = 8;</code>
+   * @return The userCycleBucket30day.
+   */
+  @java.lang.Override
+  public java.lang.String getUserCycleBucket30Day() {
+    java.lang.Object ref = userCycleBucket30Day_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      userCycleBucket30Day_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string user_cycle_bucket_30day = 8;</code>
+   * @return The bytes for userCycleBucket30day.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getUserCycleBucket30DayBytes() {
+    java.lang.Object ref = userCycleBucket30Day_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      userCycleBucket30Day_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int USER_SHARE_BUCKET_30DAY_FIELD_NUMBER = 9;
+  private volatile java.lang.Object userShareBucket30Day_;
+  /**
+   * <code>string user_share_bucket_30day = 9;</code>
+   * @return The userShareBucket30day.
+   */
+  @java.lang.Override
+  public java.lang.String getUserShareBucket30Day() {
+    java.lang.Object ref = userShareBucket30Day_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      userShareBucket30Day_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string user_share_bucket_30day = 9;</code>
+   * @return The bytes for userShareBucket30day.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getUserShareBucket30DayBytes() {
+    java.lang.Object ref = userShareBucket30Day_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      userShareBucket30Day_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
   private byte memoizedIsInitialized = -1;
   @java.lang.Override
   public final boolean isInitialized() {
@@ -94,6 +475,33 @@ private static final long serialVersionUID = 0L;
   @java.lang.Override
   public void writeTo(com.google.protobuf.CodedOutputStream output)
                       throws java.io.IOException {
+    if (!getMidBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 1, mid_);
+    }
+    if (!getUidBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 2, uid_);
+    }
+    if (day1CntFeature_ != null) {
+      output.writeMessage(3, getDay1CntFeature());
+    }
+    if (day3CntFeature_ != null) {
+      output.writeMessage(4, getDay3CntFeature());
+    }
+    if (day7CntFeature_ != null) {
+      output.writeMessage(5, getDay7CntFeature());
+    }
+    if (month3CntFeature_ != null) {
+      output.writeMessage(6, getMonth3CntFeature());
+    }
+    if (!getUserCycleBucket7DayBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 7, userCycleBucket7Day_);
+    }
+    if (!getUserCycleBucket30DayBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 8, userCycleBucket30Day_);
+    }
+    if (!getUserShareBucket30DayBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 9, userShareBucket30Day_);
+    }
     unknownFields.writeTo(output);
   }
 
@@ -103,6 +511,37 @@ private static final long serialVersionUID = 0L;
     if (size != -1) return size;
 
     size = 0;
+    if (!getMidBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, mid_);
+    }
+    if (!getUidBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, uid_);
+    }
+    if (day1CntFeature_ != null) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(3, getDay1CntFeature());
+    }
+    if (day3CntFeature_ != null) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(4, getDay3CntFeature());
+    }
+    if (day7CntFeature_ != null) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(5, getDay7CntFeature());
+    }
+    if (month3CntFeature_ != null) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(6, getMonth3CntFeature());
+    }
+    if (!getUserCycleBucket7DayBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(7, userCycleBucket7Day_);
+    }
+    if (!getUserCycleBucket30DayBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(8, userCycleBucket30Day_);
+    }
+    if (!getUserShareBucket30DayBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(9, userShareBucket30Day_);
+    }
     size += unknownFields.getSerializedSize();
     memoizedSize = size;
     return size;
@@ -118,6 +557,36 @@ private static final long serialVersionUID = 0L;
     }
     com.tzld.piaoquan.recommend.feature.model.feature.UserFeatureProto other = (com.tzld.piaoquan.recommend.feature.model.feature.UserFeatureProto) obj;
 
+    if (!getMid()
+        .equals(other.getMid())) return false;
+    if (!getUid()
+        .equals(other.getUid())) return false;
+    if (hasDay1CntFeature() != other.hasDay1CntFeature()) return false;
+    if (hasDay1CntFeature()) {
+      if (!getDay1CntFeature()
+          .equals(other.getDay1CntFeature())) return false;
+    }
+    if (hasDay3CntFeature() != other.hasDay3CntFeature()) return false;
+    if (hasDay3CntFeature()) {
+      if (!getDay3CntFeature()
+          .equals(other.getDay3CntFeature())) return false;
+    }
+    if (hasDay7CntFeature() != other.hasDay7CntFeature()) return false;
+    if (hasDay7CntFeature()) {
+      if (!getDay7CntFeature()
+          .equals(other.getDay7CntFeature())) return false;
+    }
+    if (hasMonth3CntFeature() != other.hasMonth3CntFeature()) return false;
+    if (hasMonth3CntFeature()) {
+      if (!getMonth3CntFeature()
+          .equals(other.getMonth3CntFeature())) return false;
+    }
+    if (!getUserCycleBucket7Day()
+        .equals(other.getUserCycleBucket7Day())) return false;
+    if (!getUserCycleBucket30Day()
+        .equals(other.getUserCycleBucket30Day())) return false;
+    if (!getUserShareBucket30Day()
+        .equals(other.getUserShareBucket30Day())) return false;
     if (!unknownFields.equals(other.unknownFields)) return false;
     return true;
   }
@@ -129,6 +598,32 @@ private static final long serialVersionUID = 0L;
     }
     int hash = 41;
     hash = (19 * hash) + getDescriptor().hashCode();
+    hash = (37 * hash) + MID_FIELD_NUMBER;
+    hash = (53 * hash) + getMid().hashCode();
+    hash = (37 * hash) + UID_FIELD_NUMBER;
+    hash = (53 * hash) + getUid().hashCode();
+    if (hasDay1CntFeature()) {
+      hash = (37 * hash) + DAY1_CNT_FEATURE_FIELD_NUMBER;
+      hash = (53 * hash) + getDay1CntFeature().hashCode();
+    }
+    if (hasDay3CntFeature()) {
+      hash = (37 * hash) + DAY3_CNT_FEATURE_FIELD_NUMBER;
+      hash = (53 * hash) + getDay3CntFeature().hashCode();
+    }
+    if (hasDay7CntFeature()) {
+      hash = (37 * hash) + DAY7_CNT_FEATURE_FIELD_NUMBER;
+      hash = (53 * hash) + getDay7CntFeature().hashCode();
+    }
+    if (hasMonth3CntFeature()) {
+      hash = (37 * hash) + MONTH3_CNT_FEATURE_FIELD_NUMBER;
+      hash = (53 * hash) + getMonth3CntFeature().hashCode();
+    }
+    hash = (37 * hash) + USER_CYCLE_BUCKET_7DAY_FIELD_NUMBER;
+    hash = (53 * hash) + getUserCycleBucket7Day().hashCode();
+    hash = (37 * hash) + USER_CYCLE_BUCKET_30DAY_FIELD_NUMBER;
+    hash = (53 * hash) + getUserCycleBucket30Day().hashCode();
+    hash = (37 * hash) + USER_SHARE_BUCKET_30DAY_FIELD_NUMBER;
+    hash = (53 * hash) + getUserShareBucket30Day().hashCode();
     hash = (29 * hash) + unknownFields.hashCode();
     memoizedHashCode = hash;
     return hash;
@@ -262,6 +757,40 @@ private static final long serialVersionUID = 0L;
     @java.lang.Override
     public Builder clear() {
       super.clear();
+      mid_ = "";
+
+      uid_ = "";
+
+      if (day1CntFeatureBuilder_ == null) {
+        day1CntFeature_ = null;
+      } else {
+        day1CntFeature_ = null;
+        day1CntFeatureBuilder_ = null;
+      }
+      if (day3CntFeatureBuilder_ == null) {
+        day3CntFeature_ = null;
+      } else {
+        day3CntFeature_ = null;
+        day3CntFeatureBuilder_ = null;
+      }
+      if (day7CntFeatureBuilder_ == null) {
+        day7CntFeature_ = null;
+      } else {
+        day7CntFeature_ = null;
+        day7CntFeatureBuilder_ = null;
+      }
+      if (month3CntFeatureBuilder_ == null) {
+        month3CntFeature_ = null;
+      } else {
+        month3CntFeature_ = null;
+        month3CntFeatureBuilder_ = null;
+      }
+      userCycleBucket7Day_ = "";
+
+      userCycleBucket30Day_ = "";
+
+      userShareBucket30Day_ = "";
+
       return this;
     }
 
@@ -288,6 +817,31 @@ private static final long serialVersionUID = 0L;
     @java.lang.Override
     public com.tzld.piaoquan.recommend.feature.model.feature.UserFeatureProto buildPartial() {
       com.tzld.piaoquan.recommend.feature.model.feature.UserFeatureProto result = new com.tzld.piaoquan.recommend.feature.model.feature.UserFeatureProto(this);
+      result.mid_ = mid_;
+      result.uid_ = uid_;
+      if (day1CntFeatureBuilder_ == null) {
+        result.day1CntFeature_ = day1CntFeature_;
+      } else {
+        result.day1CntFeature_ = day1CntFeatureBuilder_.build();
+      }
+      if (day3CntFeatureBuilder_ == null) {
+        result.day3CntFeature_ = day3CntFeature_;
+      } else {
+        result.day3CntFeature_ = day3CntFeatureBuilder_.build();
+      }
+      if (day7CntFeatureBuilder_ == null) {
+        result.day7CntFeature_ = day7CntFeature_;
+      } else {
+        result.day7CntFeature_ = day7CntFeatureBuilder_.build();
+      }
+      if (month3CntFeatureBuilder_ == null) {
+        result.month3CntFeature_ = month3CntFeature_;
+      } else {
+        result.month3CntFeature_ = month3CntFeatureBuilder_.build();
+      }
+      result.userCycleBucket7Day_ = userCycleBucket7Day_;
+      result.userCycleBucket30Day_ = userCycleBucket30Day_;
+      result.userShareBucket30Day_ = userShareBucket30Day_;
       onBuilt();
       return result;
     }
@@ -336,6 +890,38 @@ private static final long serialVersionUID = 0L;
 
     public Builder mergeFrom(com.tzld.piaoquan.recommend.feature.model.feature.UserFeatureProto other) {
       if (other == com.tzld.piaoquan.recommend.feature.model.feature.UserFeatureProto.getDefaultInstance()) return this;
+      if (!other.getMid().isEmpty()) {
+        mid_ = other.mid_;
+        onChanged();
+      }
+      if (!other.getUid().isEmpty()) {
+        uid_ = other.uid_;
+        onChanged();
+      }
+      if (other.hasDay1CntFeature()) {
+        mergeDay1CntFeature(other.getDay1CntFeature());
+      }
+      if (other.hasDay3CntFeature()) {
+        mergeDay3CntFeature(other.getDay3CntFeature());
+      }
+      if (other.hasDay7CntFeature()) {
+        mergeDay7CntFeature(other.getDay7CntFeature());
+      }
+      if (other.hasMonth3CntFeature()) {
+        mergeMonth3CntFeature(other.getMonth3CntFeature());
+      }
+      if (!other.getUserCycleBucket7Day().isEmpty()) {
+        userCycleBucket7Day_ = other.userCycleBucket7Day_;
+        onChanged();
+      }
+      if (!other.getUserCycleBucket30Day().isEmpty()) {
+        userCycleBucket30Day_ = other.userCycleBucket30Day_;
+        onChanged();
+      }
+      if (!other.getUserShareBucket30Day().isEmpty()) {
+        userShareBucket30Day_ = other.userShareBucket30Day_;
+        onChanged();
+      }
       this.mergeUnknownFields(other.unknownFields);
       onChanged();
       return this;
@@ -364,6 +950,862 @@ private static final long serialVersionUID = 0L;
       }
       return this;
     }
+
+    private java.lang.Object mid_ = "";
+    /**
+     * <code>string mid = 1;</code>
+     * @return The mid.
+     */
+    public java.lang.String getMid() {
+      java.lang.Object ref = mid_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        mid_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string mid = 1;</code>
+     * @return The bytes for mid.
+     */
+    public com.google.protobuf.ByteString
+        getMidBytes() {
+      java.lang.Object ref = mid_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        mid_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string mid = 1;</code>
+     * @param value The mid to set.
+     * @return This builder for chaining.
+     */
+    public Builder setMid(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      mid_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string mid = 1;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearMid() {
+      
+      mid_ = getDefaultInstance().getMid();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string mid = 1;</code>
+     * @param value The bytes for mid to set.
+     * @return This builder for chaining.
+     */
+    public Builder setMidBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      mid_ = value;
+      onChanged();
+      return this;
+    }
+
+    private java.lang.Object uid_ = "";
+    /**
+     * <code>string uid = 2;</code>
+     * @return The uid.
+     */
+    public java.lang.String getUid() {
+      java.lang.Object ref = uid_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        uid_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string uid = 2;</code>
+     * @return The bytes for uid.
+     */
+    public com.google.protobuf.ByteString
+        getUidBytes() {
+      java.lang.Object ref = uid_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        uid_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string uid = 2;</code>
+     * @param value The uid to set.
+     * @return This builder for chaining.
+     */
+    public Builder setUid(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      uid_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string uid = 2;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearUid() {
+      
+      uid_ = getDefaultInstance().getUid();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string uid = 2;</code>
+     * @param value The bytes for uid to set.
+     * @return This builder for chaining.
+     */
+    public Builder setUidBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      uid_ = value;
+      onChanged();
+      return this;
+    }
+
+    private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto day1CntFeature_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> day1CntFeatureBuilder_;
+    /**
+     * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+     * @return Whether the day1CntFeature field is set.
+     */
+    public boolean hasDay1CntFeature() {
+      return day1CntFeatureBuilder_ != null || day1CntFeature_ != null;
+    }
+    /**
+     * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+     * @return The day1CntFeature.
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDay1CntFeature() {
+      if (day1CntFeatureBuilder_ == null) {
+        return day1CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : day1CntFeature_;
+      } else {
+        return day1CntFeatureBuilder_.getMessage();
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+     */
+    public Builder setDay1CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (day1CntFeatureBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        day1CntFeature_ = value;
+        onChanged();
+      } else {
+        day1CntFeatureBuilder_.setMessage(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+     */
+    public Builder setDay1CntFeature(
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder builderForValue) {
+      if (day1CntFeatureBuilder_ == null) {
+        day1CntFeature_ = builderForValue.build();
+        onChanged();
+      } else {
+        day1CntFeatureBuilder_.setMessage(builderForValue.build());
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+     */
+    public Builder mergeDay1CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (day1CntFeatureBuilder_ == null) {
+        if (day1CntFeature_ != null) {
+          day1CntFeature_ =
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.newBuilder(day1CntFeature_).mergeFrom(value).buildPartial();
+        } else {
+          day1CntFeature_ = value;
+        }
+        onChanged();
+      } else {
+        day1CntFeatureBuilder_.mergeFrom(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+     */
+    public Builder clearDay1CntFeature() {
+      if (day1CntFeatureBuilder_ == null) {
+        day1CntFeature_ = null;
+        onChanged();
+      } else {
+        day1CntFeature_ = null;
+        day1CntFeatureBuilder_ = null;
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder getDay1CntFeatureBuilder() {
+      
+      onChanged();
+      return getDay1CntFeatureFieldBuilder().getBuilder();
+    }
+    /**
+     * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getDay1CntFeatureOrBuilder() {
+      if (day1CntFeatureBuilder_ != null) {
+        return day1CntFeatureBuilder_.getMessageOrBuilder();
+      } else {
+        return day1CntFeature_ == null ?
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : day1CntFeature_;
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> 
+        getDay1CntFeatureFieldBuilder() {
+      if (day1CntFeatureBuilder_ == null) {
+        day1CntFeatureBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder>(
+                getDay1CntFeature(),
+                getParentForChildren(),
+                isClean());
+        day1CntFeature_ = null;
+      }
+      return day1CntFeatureBuilder_;
+    }
+
+    private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto day3CntFeature_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> day3CntFeatureBuilder_;
+    /**
+     * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+     * @return Whether the day3CntFeature field is set.
+     */
+    public boolean hasDay3CntFeature() {
+      return day3CntFeatureBuilder_ != null || day3CntFeature_ != null;
+    }
+    /**
+     * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+     * @return The day3CntFeature.
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDay3CntFeature() {
+      if (day3CntFeatureBuilder_ == null) {
+        return day3CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : day3CntFeature_;
+      } else {
+        return day3CntFeatureBuilder_.getMessage();
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+     */
+    public Builder setDay3CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (day3CntFeatureBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        day3CntFeature_ = value;
+        onChanged();
+      } else {
+        day3CntFeatureBuilder_.setMessage(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+     */
+    public Builder setDay3CntFeature(
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder builderForValue) {
+      if (day3CntFeatureBuilder_ == null) {
+        day3CntFeature_ = builderForValue.build();
+        onChanged();
+      } else {
+        day3CntFeatureBuilder_.setMessage(builderForValue.build());
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+     */
+    public Builder mergeDay3CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (day3CntFeatureBuilder_ == null) {
+        if (day3CntFeature_ != null) {
+          day3CntFeature_ =
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.newBuilder(day3CntFeature_).mergeFrom(value).buildPartial();
+        } else {
+          day3CntFeature_ = value;
+        }
+        onChanged();
+      } else {
+        day3CntFeatureBuilder_.mergeFrom(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+     */
+    public Builder clearDay3CntFeature() {
+      if (day3CntFeatureBuilder_ == null) {
+        day3CntFeature_ = null;
+        onChanged();
+      } else {
+        day3CntFeature_ = null;
+        day3CntFeatureBuilder_ = null;
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder getDay3CntFeatureBuilder() {
+      
+      onChanged();
+      return getDay3CntFeatureFieldBuilder().getBuilder();
+    }
+    /**
+     * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getDay3CntFeatureOrBuilder() {
+      if (day3CntFeatureBuilder_ != null) {
+        return day3CntFeatureBuilder_.getMessageOrBuilder();
+      } else {
+        return day3CntFeature_ == null ?
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : day3CntFeature_;
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> 
+        getDay3CntFeatureFieldBuilder() {
+      if (day3CntFeatureBuilder_ == null) {
+        day3CntFeatureBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder>(
+                getDay3CntFeature(),
+                getParentForChildren(),
+                isClean());
+        day3CntFeature_ = null;
+      }
+      return day3CntFeatureBuilder_;
+    }
+
+    private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto day7CntFeature_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> day7CntFeatureBuilder_;
+    /**
+     * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+     * @return Whether the day7CntFeature field is set.
+     */
+    public boolean hasDay7CntFeature() {
+      return day7CntFeatureBuilder_ != null || day7CntFeature_ != null;
+    }
+    /**
+     * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+     * @return The day7CntFeature.
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDay7CntFeature() {
+      if (day7CntFeatureBuilder_ == null) {
+        return day7CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : day7CntFeature_;
+      } else {
+        return day7CntFeatureBuilder_.getMessage();
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+     */
+    public Builder setDay7CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (day7CntFeatureBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        day7CntFeature_ = value;
+        onChanged();
+      } else {
+        day7CntFeatureBuilder_.setMessage(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+     */
+    public Builder setDay7CntFeature(
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder builderForValue) {
+      if (day7CntFeatureBuilder_ == null) {
+        day7CntFeature_ = builderForValue.build();
+        onChanged();
+      } else {
+        day7CntFeatureBuilder_.setMessage(builderForValue.build());
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+     */
+    public Builder mergeDay7CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (day7CntFeatureBuilder_ == null) {
+        if (day7CntFeature_ != null) {
+          day7CntFeature_ =
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.newBuilder(day7CntFeature_).mergeFrom(value).buildPartial();
+        } else {
+          day7CntFeature_ = value;
+        }
+        onChanged();
+      } else {
+        day7CntFeatureBuilder_.mergeFrom(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+     */
+    public Builder clearDay7CntFeature() {
+      if (day7CntFeatureBuilder_ == null) {
+        day7CntFeature_ = null;
+        onChanged();
+      } else {
+        day7CntFeature_ = null;
+        day7CntFeatureBuilder_ = null;
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder getDay7CntFeatureBuilder() {
+      
+      onChanged();
+      return getDay7CntFeatureFieldBuilder().getBuilder();
+    }
+    /**
+     * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getDay7CntFeatureOrBuilder() {
+      if (day7CntFeatureBuilder_ != null) {
+        return day7CntFeatureBuilder_.getMessageOrBuilder();
+      } else {
+        return day7CntFeature_ == null ?
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : day7CntFeature_;
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> 
+        getDay7CntFeatureFieldBuilder() {
+      if (day7CntFeatureBuilder_ == null) {
+        day7CntFeatureBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder>(
+                getDay7CntFeature(),
+                getParentForChildren(),
+                isClean());
+        day7CntFeature_ = null;
+      }
+      return day7CntFeatureBuilder_;
+    }
+
+    private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto month3CntFeature_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> month3CntFeatureBuilder_;
+    /**
+     * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+     * @return Whether the month3CntFeature field is set.
+     */
+    public boolean hasMonth3CntFeature() {
+      return month3CntFeatureBuilder_ != null || month3CntFeature_ != null;
+    }
+    /**
+     * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+     * @return The month3CntFeature.
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getMonth3CntFeature() {
+      if (month3CntFeatureBuilder_ == null) {
+        return month3CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : month3CntFeature_;
+      } else {
+        return month3CntFeatureBuilder_.getMessage();
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+     */
+    public Builder setMonth3CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (month3CntFeatureBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        month3CntFeature_ = value;
+        onChanged();
+      } else {
+        month3CntFeatureBuilder_.setMessage(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+     */
+    public Builder setMonth3CntFeature(
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder builderForValue) {
+      if (month3CntFeatureBuilder_ == null) {
+        month3CntFeature_ = builderForValue.build();
+        onChanged();
+      } else {
+        month3CntFeatureBuilder_.setMessage(builderForValue.build());
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+     */
+    public Builder mergeMonth3CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (month3CntFeatureBuilder_ == null) {
+        if (month3CntFeature_ != null) {
+          month3CntFeature_ =
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.newBuilder(month3CntFeature_).mergeFrom(value).buildPartial();
+        } else {
+          month3CntFeature_ = value;
+        }
+        onChanged();
+      } else {
+        month3CntFeatureBuilder_.mergeFrom(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+     */
+    public Builder clearMonth3CntFeature() {
+      if (month3CntFeatureBuilder_ == null) {
+        month3CntFeature_ = null;
+        onChanged();
+      } else {
+        month3CntFeature_ = null;
+        month3CntFeatureBuilder_ = null;
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder getMonth3CntFeatureBuilder() {
+      
+      onChanged();
+      return getMonth3CntFeatureFieldBuilder().getBuilder();
+    }
+    /**
+     * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getMonth3CntFeatureOrBuilder() {
+      if (month3CntFeatureBuilder_ != null) {
+        return month3CntFeatureBuilder_.getMessageOrBuilder();
+      } else {
+        return month3CntFeature_ == null ?
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : month3CntFeature_;
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> 
+        getMonth3CntFeatureFieldBuilder() {
+      if (month3CntFeatureBuilder_ == null) {
+        month3CntFeatureBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder>(
+                getMonth3CntFeature(),
+                getParentForChildren(),
+                isClean());
+        month3CntFeature_ = null;
+      }
+      return month3CntFeatureBuilder_;
+    }
+
+    private java.lang.Object userCycleBucket7Day_ = "";
+    /**
+     * <code>string user_cycle_bucket_7day = 7;</code>
+     * @return The userCycleBucket7day.
+     */
+    public java.lang.String getUserCycleBucket7Day() {
+      java.lang.Object ref = userCycleBucket7Day_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        userCycleBucket7Day_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string user_cycle_bucket_7day = 7;</code>
+     * @return The bytes for userCycleBucket7day.
+     */
+    public com.google.protobuf.ByteString
+        getUserCycleBucket7DayBytes() {
+      java.lang.Object ref = userCycleBucket7Day_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        userCycleBucket7Day_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string user_cycle_bucket_7day = 7;</code>
+     * @param value The userCycleBucket7day to set.
+     * @return This builder for chaining.
+     */
+    public Builder setUserCycleBucket7Day(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      userCycleBucket7Day_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string user_cycle_bucket_7day = 7;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearUserCycleBucket7Day() {
+      
+      userCycleBucket7Day_ = getDefaultInstance().getUserCycleBucket7Day();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string user_cycle_bucket_7day = 7;</code>
+     * @param value The bytes for userCycleBucket7day to set.
+     * @return This builder for chaining.
+     */
+    public Builder setUserCycleBucket7DayBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      userCycleBucket7Day_ = value;
+      onChanged();
+      return this;
+    }
+
+    private java.lang.Object userCycleBucket30Day_ = "";
+    /**
+     * <code>string user_cycle_bucket_30day = 8;</code>
+     * @return The userCycleBucket30day.
+     */
+    public java.lang.String getUserCycleBucket30Day() {
+      java.lang.Object ref = userCycleBucket30Day_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        userCycleBucket30Day_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string user_cycle_bucket_30day = 8;</code>
+     * @return The bytes for userCycleBucket30day.
+     */
+    public com.google.protobuf.ByteString
+        getUserCycleBucket30DayBytes() {
+      java.lang.Object ref = userCycleBucket30Day_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        userCycleBucket30Day_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string user_cycle_bucket_30day = 8;</code>
+     * @param value The userCycleBucket30day to set.
+     * @return This builder for chaining.
+     */
+    public Builder setUserCycleBucket30Day(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      userCycleBucket30Day_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string user_cycle_bucket_30day = 8;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearUserCycleBucket30Day() {
+      
+      userCycleBucket30Day_ = getDefaultInstance().getUserCycleBucket30Day();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string user_cycle_bucket_30day = 8;</code>
+     * @param value The bytes for userCycleBucket30day to set.
+     * @return This builder for chaining.
+     */
+    public Builder setUserCycleBucket30DayBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      userCycleBucket30Day_ = value;
+      onChanged();
+      return this;
+    }
+
+    private java.lang.Object userShareBucket30Day_ = "";
+    /**
+     * <code>string user_share_bucket_30day = 9;</code>
+     * @return The userShareBucket30day.
+     */
+    public java.lang.String getUserShareBucket30Day() {
+      java.lang.Object ref = userShareBucket30Day_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        userShareBucket30Day_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string user_share_bucket_30day = 9;</code>
+     * @return The bytes for userShareBucket30day.
+     */
+    public com.google.protobuf.ByteString
+        getUserShareBucket30DayBytes() {
+      java.lang.Object ref = userShareBucket30Day_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        userShareBucket30Day_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string user_share_bucket_30day = 9;</code>
+     * @param value The userShareBucket30day to set.
+     * @return This builder for chaining.
+     */
+    public Builder setUserShareBucket30Day(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      userShareBucket30Day_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string user_share_bucket_30day = 9;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearUserShareBucket30Day() {
+      
+      userShareBucket30Day_ = getDefaultInstance().getUserShareBucket30Day();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string user_share_bucket_30day = 9;</code>
+     * @param value The bytes for userShareBucket30day to set.
+     * @return This builder for chaining.
+     */
+    public Builder setUserShareBucket30DayBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      userShareBucket30Day_ = value;
+      onChanged();
+      return this;
+    }
     @java.lang.Override
     public final Builder setUnknownFields(
         final com.google.protobuf.UnknownFieldSet unknownFields) {

+ 120 - 0
recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/UserFeatureProtoOrBuilder.java

@@ -6,4 +6,124 @@ package com.tzld.piaoquan.recommend.feature.model.feature;
 public interface UserFeatureProtoOrBuilder extends
     // @@protoc_insertion_point(interface_extends:UserFeatureProto)
     com.google.protobuf.MessageOrBuilder {
+
+  /**
+   * <code>string mid = 1;</code>
+   * @return The mid.
+   */
+  java.lang.String getMid();
+  /**
+   * <code>string mid = 1;</code>
+   * @return The bytes for mid.
+   */
+  com.google.protobuf.ByteString
+      getMidBytes();
+
+  /**
+   * <code>string uid = 2;</code>
+   * @return The uid.
+   */
+  java.lang.String getUid();
+  /**
+   * <code>string uid = 2;</code>
+   * @return The bytes for uid.
+   */
+  com.google.protobuf.ByteString
+      getUidBytes();
+
+  /**
+   * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+   * @return Whether the day1CntFeature field is set.
+   */
+  boolean hasDay1CntFeature();
+  /**
+   * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+   * @return The day1CntFeature.
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDay1CntFeature();
+  /**
+   * <code>.UserActionFeatureProto day1_cnt_feature = 3;</code>
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getDay1CntFeatureOrBuilder();
+
+  /**
+   * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+   * @return Whether the day3CntFeature field is set.
+   */
+  boolean hasDay3CntFeature();
+  /**
+   * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+   * @return The day3CntFeature.
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDay3CntFeature();
+  /**
+   * <code>.UserActionFeatureProto day3_cnt_feature = 4;</code>
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getDay3CntFeatureOrBuilder();
+
+  /**
+   * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+   * @return Whether the day7CntFeature field is set.
+   */
+  boolean hasDay7CntFeature();
+  /**
+   * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+   * @return The day7CntFeature.
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getDay7CntFeature();
+  /**
+   * <code>.UserActionFeatureProto day7_cnt_feature = 5;</code>
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getDay7CntFeatureOrBuilder();
+
+  /**
+   * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+   * @return Whether the month3CntFeature field is set.
+   */
+  boolean hasMonth3CntFeature();
+  /**
+   * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+   * @return The month3CntFeature.
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getMonth3CntFeature();
+  /**
+   * <code>.UserActionFeatureProto month3_cnt_feature = 6;</code>
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getMonth3CntFeatureOrBuilder();
+
+  /**
+   * <code>string user_cycle_bucket_7day = 7;</code>
+   * @return The userCycleBucket7day.
+   */
+  java.lang.String getUserCycleBucket7Day();
+  /**
+   * <code>string user_cycle_bucket_7day = 7;</code>
+   * @return The bytes for userCycleBucket7day.
+   */
+  com.google.protobuf.ByteString
+      getUserCycleBucket7DayBytes();
+
+  /**
+   * <code>string user_cycle_bucket_30day = 8;</code>
+   * @return The userCycleBucket30day.
+   */
+  java.lang.String getUserCycleBucket30Day();
+  /**
+   * <code>string user_cycle_bucket_30day = 8;</code>
+   * @return The bytes for userCycleBucket30day.
+   */
+  com.google.protobuf.ByteString
+      getUserCycleBucket30DayBytes();
+
+  /**
+   * <code>string user_share_bucket_30day = 9;</code>
+   * @return The userShareBucket30day.
+   */
+  java.lang.String getUserShareBucket30Day();
+  /**
+   * <code>string user_share_bucket_30day = 9;</code>
+   * @return The bytes for userShareBucket30day.
+   */
+  com.google.protobuf.ByteString
+      getUserShareBucket30DayBytes();
 }

+ 1580 - 0
recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/VideoFeatureProto.java

@@ -16,6 +16,12 @@ private static final long serialVersionUID = 0L;
     super(builder);
   }
   private VideoFeatureProto() {
+    videoId_ = "";
+    upId_ = "";
+    tags_ = "";
+    playLength_ = "";
+    totalTime_ = "";
+    daysSinceUpload_ = "";
   }
 
   @java.lang.Override
@@ -48,6 +54,94 @@ private static final long serialVersionUID = 0L;
           case 0:
             done = true;
             break;
+          case 10: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            videoId_ = s;
+            break;
+          }
+          case 18: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            upId_ = s;
+            break;
+          }
+          case 26: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            tags_ = s;
+            break;
+          }
+          case 34: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            playLength_ = s;
+            break;
+          }
+          case 42: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            totalTime_ = s;
+            break;
+          }
+          case 50: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            daysSinceUpload_ = s;
+            break;
+          }
+          case 58: {
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder subBuilder = null;
+            if (videoDay1CntFeature_ != null) {
+              subBuilder = videoDay1CntFeature_.toBuilder();
+            }
+            videoDay1CntFeature_ = input.readMessage(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.parser(), extensionRegistry);
+            if (subBuilder != null) {
+              subBuilder.mergeFrom(videoDay1CntFeature_);
+              videoDay1CntFeature_ = subBuilder.buildPartial();
+            }
+
+            break;
+          }
+          case 66: {
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder subBuilder = null;
+            if (videoDay3CntFeature_ != null) {
+              subBuilder = videoDay3CntFeature_.toBuilder();
+            }
+            videoDay3CntFeature_ = input.readMessage(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.parser(), extensionRegistry);
+            if (subBuilder != null) {
+              subBuilder.mergeFrom(videoDay3CntFeature_);
+              videoDay3CntFeature_ = subBuilder.buildPartial();
+            }
+
+            break;
+          }
+          case 74: {
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder subBuilder = null;
+            if (videoDay7CntFeature_ != null) {
+              subBuilder = videoDay7CntFeature_.toBuilder();
+            }
+            videoDay7CntFeature_ = input.readMessage(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.parser(), extensionRegistry);
+            if (subBuilder != null) {
+              subBuilder.mergeFrom(videoDay7CntFeature_);
+              videoDay7CntFeature_ = subBuilder.buildPartial();
+            }
+
+            break;
+          }
+          case 82: {
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder subBuilder = null;
+            if (videoMonth3CntFeature_ != null) {
+              subBuilder = videoMonth3CntFeature_.toBuilder();
+            }
+            videoMonth3CntFeature_ = input.readMessage(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.parser(), extensionRegistry);
+            if (subBuilder != null) {
+              subBuilder.mergeFrom(videoMonth3CntFeature_);
+              videoMonth3CntFeature_ = subBuilder.buildPartial();
+            }
+
+            break;
+          }
           default: {
             if (!parseUnknownField(
                 input, unknownFields, extensionRegistry, tag)) {
@@ -80,6 +174,338 @@ private static final long serialVersionUID = 0L;
             com.tzld.piaoquan.recommend.feature.model.feature.VideoFeatureProto.class, com.tzld.piaoquan.recommend.feature.model.feature.VideoFeatureProto.Builder.class);
   }
 
+  public static final int VIDEO_ID_FIELD_NUMBER = 1;
+  private volatile java.lang.Object videoId_;
+  /**
+   * <code>string video_id = 1;</code>
+   * @return The videoId.
+   */
+  @java.lang.Override
+  public java.lang.String getVideoId() {
+    java.lang.Object ref = videoId_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      videoId_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string video_id = 1;</code>
+   * @return The bytes for videoId.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getVideoIdBytes() {
+    java.lang.Object ref = videoId_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      videoId_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int UP_ID_FIELD_NUMBER = 2;
+  private volatile java.lang.Object upId_;
+  /**
+   * <code>string up_id = 2;</code>
+   * @return The upId.
+   */
+  @java.lang.Override
+  public java.lang.String getUpId() {
+    java.lang.Object ref = upId_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      upId_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string up_id = 2;</code>
+   * @return The bytes for upId.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getUpIdBytes() {
+    java.lang.Object ref = upId_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      upId_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int TAGS_FIELD_NUMBER = 3;
+  private volatile java.lang.Object tags_;
+  /**
+   * <code>string tags = 3;</code>
+   * @return The tags.
+   */
+  @java.lang.Override
+  public java.lang.String getTags() {
+    java.lang.Object ref = tags_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      tags_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string tags = 3;</code>
+   * @return The bytes for tags.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getTagsBytes() {
+    java.lang.Object ref = tags_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      tags_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int PLAY_LENGTH_FIELD_NUMBER = 4;
+  private volatile java.lang.Object playLength_;
+  /**
+   * <code>string play_length = 4;</code>
+   * @return The playLength.
+   */
+  @java.lang.Override
+  public java.lang.String getPlayLength() {
+    java.lang.Object ref = playLength_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      playLength_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string play_length = 4;</code>
+   * @return The bytes for playLength.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getPlayLengthBytes() {
+    java.lang.Object ref = playLength_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      playLength_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int TOTAL_TIME_FIELD_NUMBER = 5;
+  private volatile java.lang.Object totalTime_;
+  /**
+   * <code>string total_time = 5;</code>
+   * @return The totalTime.
+   */
+  @java.lang.Override
+  public java.lang.String getTotalTime() {
+    java.lang.Object ref = totalTime_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      totalTime_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string total_time = 5;</code>
+   * @return The bytes for totalTime.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getTotalTimeBytes() {
+    java.lang.Object ref = totalTime_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      totalTime_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int DAYS_SINCE_UPLOAD_FIELD_NUMBER = 6;
+  private volatile java.lang.Object daysSinceUpload_;
+  /**
+   * <code>string days_since_upload = 6;</code>
+   * @return The daysSinceUpload.
+   */
+  @java.lang.Override
+  public java.lang.String getDaysSinceUpload() {
+    java.lang.Object ref = daysSinceUpload_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      daysSinceUpload_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string days_since_upload = 6;</code>
+   * @return The bytes for daysSinceUpload.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getDaysSinceUploadBytes() {
+    java.lang.Object ref = daysSinceUpload_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      daysSinceUpload_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int VIDEO_DAY1_CNT_FEATURE_FIELD_NUMBER = 7;
+  private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto videoDay1CntFeature_;
+  /**
+   * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+   * @return Whether the videoDay1CntFeature field is set.
+   */
+  @java.lang.Override
+  public boolean hasVideoDay1CntFeature() {
+    return videoDay1CntFeature_ != null;
+  }
+  /**
+   * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+   * @return The videoDay1CntFeature.
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoDay1CntFeature() {
+    return videoDay1CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoDay1CntFeature_;
+  }
+  /**
+   * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoDay1CntFeatureOrBuilder() {
+    return getVideoDay1CntFeature();
+  }
+
+  public static final int VIDEO_DAY3_CNT_FEATURE_FIELD_NUMBER = 8;
+  private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto videoDay3CntFeature_;
+  /**
+   * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+   * @return Whether the videoDay3CntFeature field is set.
+   */
+  @java.lang.Override
+  public boolean hasVideoDay3CntFeature() {
+    return videoDay3CntFeature_ != null;
+  }
+  /**
+   * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+   * @return The videoDay3CntFeature.
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoDay3CntFeature() {
+    return videoDay3CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoDay3CntFeature_;
+  }
+  /**
+   * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoDay3CntFeatureOrBuilder() {
+    return getVideoDay3CntFeature();
+  }
+
+  public static final int VIDEO_DAY7_CNT_FEATURE_FIELD_NUMBER = 9;
+  private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto videoDay7CntFeature_;
+  /**
+   * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+   * @return Whether the videoDay7CntFeature field is set.
+   */
+  @java.lang.Override
+  public boolean hasVideoDay7CntFeature() {
+    return videoDay7CntFeature_ != null;
+  }
+  /**
+   * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+   * @return The videoDay7CntFeature.
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoDay7CntFeature() {
+    return videoDay7CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoDay7CntFeature_;
+  }
+  /**
+   * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoDay7CntFeatureOrBuilder() {
+    return getVideoDay7CntFeature();
+  }
+
+  public static final int VIDEO_MONTH3_CNT_FEATURE_FIELD_NUMBER = 10;
+  private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto videoMonth3CntFeature_;
+  /**
+   * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+   * @return Whether the videoMonth3CntFeature field is set.
+   */
+  @java.lang.Override
+  public boolean hasVideoMonth3CntFeature() {
+    return videoMonth3CntFeature_ != null;
+  }
+  /**
+   * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+   * @return The videoMonth3CntFeature.
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoMonth3CntFeature() {
+    return videoMonth3CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoMonth3CntFeature_;
+  }
+  /**
+   * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoMonth3CntFeatureOrBuilder() {
+    return getVideoMonth3CntFeature();
+  }
+
   private byte memoizedIsInitialized = -1;
   @java.lang.Override
   public final boolean isInitialized() {
@@ -94,6 +520,36 @@ private static final long serialVersionUID = 0L;
   @java.lang.Override
   public void writeTo(com.google.protobuf.CodedOutputStream output)
                       throws java.io.IOException {
+    if (!getVideoIdBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 1, videoId_);
+    }
+    if (!getUpIdBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 2, upId_);
+    }
+    if (!getTagsBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 3, tags_);
+    }
+    if (!getPlayLengthBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 4, playLength_);
+    }
+    if (!getTotalTimeBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 5, totalTime_);
+    }
+    if (!getDaysSinceUploadBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 6, daysSinceUpload_);
+    }
+    if (videoDay1CntFeature_ != null) {
+      output.writeMessage(7, getVideoDay1CntFeature());
+    }
+    if (videoDay3CntFeature_ != null) {
+      output.writeMessage(8, getVideoDay3CntFeature());
+    }
+    if (videoDay7CntFeature_ != null) {
+      output.writeMessage(9, getVideoDay7CntFeature());
+    }
+    if (videoMonth3CntFeature_ != null) {
+      output.writeMessage(10, getVideoMonth3CntFeature());
+    }
     unknownFields.writeTo(output);
   }
 
@@ -103,6 +559,40 @@ private static final long serialVersionUID = 0L;
     if (size != -1) return size;
 
     size = 0;
+    if (!getVideoIdBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, videoId_);
+    }
+    if (!getUpIdBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, upId_);
+    }
+    if (!getTagsBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, tags_);
+    }
+    if (!getPlayLengthBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, playLength_);
+    }
+    if (!getTotalTimeBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(5, totalTime_);
+    }
+    if (!getDaysSinceUploadBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(6, daysSinceUpload_);
+    }
+    if (videoDay1CntFeature_ != null) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(7, getVideoDay1CntFeature());
+    }
+    if (videoDay3CntFeature_ != null) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(8, getVideoDay3CntFeature());
+    }
+    if (videoDay7CntFeature_ != null) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(9, getVideoDay7CntFeature());
+    }
+    if (videoMonth3CntFeature_ != null) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(10, getVideoMonth3CntFeature());
+    }
     size += unknownFields.getSerializedSize();
     memoizedSize = size;
     return size;
@@ -118,6 +608,38 @@ private static final long serialVersionUID = 0L;
     }
     com.tzld.piaoquan.recommend.feature.model.feature.VideoFeatureProto other = (com.tzld.piaoquan.recommend.feature.model.feature.VideoFeatureProto) obj;
 
+    if (!getVideoId()
+        .equals(other.getVideoId())) return false;
+    if (!getUpId()
+        .equals(other.getUpId())) return false;
+    if (!getTags()
+        .equals(other.getTags())) return false;
+    if (!getPlayLength()
+        .equals(other.getPlayLength())) return false;
+    if (!getTotalTime()
+        .equals(other.getTotalTime())) return false;
+    if (!getDaysSinceUpload()
+        .equals(other.getDaysSinceUpload())) return false;
+    if (hasVideoDay1CntFeature() != other.hasVideoDay1CntFeature()) return false;
+    if (hasVideoDay1CntFeature()) {
+      if (!getVideoDay1CntFeature()
+          .equals(other.getVideoDay1CntFeature())) return false;
+    }
+    if (hasVideoDay3CntFeature() != other.hasVideoDay3CntFeature()) return false;
+    if (hasVideoDay3CntFeature()) {
+      if (!getVideoDay3CntFeature()
+          .equals(other.getVideoDay3CntFeature())) return false;
+    }
+    if (hasVideoDay7CntFeature() != other.hasVideoDay7CntFeature()) return false;
+    if (hasVideoDay7CntFeature()) {
+      if (!getVideoDay7CntFeature()
+          .equals(other.getVideoDay7CntFeature())) return false;
+    }
+    if (hasVideoMonth3CntFeature() != other.hasVideoMonth3CntFeature()) return false;
+    if (hasVideoMonth3CntFeature()) {
+      if (!getVideoMonth3CntFeature()
+          .equals(other.getVideoMonth3CntFeature())) return false;
+    }
     if (!unknownFields.equals(other.unknownFields)) return false;
     return true;
   }
@@ -129,6 +651,34 @@ private static final long serialVersionUID = 0L;
     }
     int hash = 41;
     hash = (19 * hash) + getDescriptor().hashCode();
+    hash = (37 * hash) + VIDEO_ID_FIELD_NUMBER;
+    hash = (53 * hash) + getVideoId().hashCode();
+    hash = (37 * hash) + UP_ID_FIELD_NUMBER;
+    hash = (53 * hash) + getUpId().hashCode();
+    hash = (37 * hash) + TAGS_FIELD_NUMBER;
+    hash = (53 * hash) + getTags().hashCode();
+    hash = (37 * hash) + PLAY_LENGTH_FIELD_NUMBER;
+    hash = (53 * hash) + getPlayLength().hashCode();
+    hash = (37 * hash) + TOTAL_TIME_FIELD_NUMBER;
+    hash = (53 * hash) + getTotalTime().hashCode();
+    hash = (37 * hash) + DAYS_SINCE_UPLOAD_FIELD_NUMBER;
+    hash = (53 * hash) + getDaysSinceUpload().hashCode();
+    if (hasVideoDay1CntFeature()) {
+      hash = (37 * hash) + VIDEO_DAY1_CNT_FEATURE_FIELD_NUMBER;
+      hash = (53 * hash) + getVideoDay1CntFeature().hashCode();
+    }
+    if (hasVideoDay3CntFeature()) {
+      hash = (37 * hash) + VIDEO_DAY3_CNT_FEATURE_FIELD_NUMBER;
+      hash = (53 * hash) + getVideoDay3CntFeature().hashCode();
+    }
+    if (hasVideoDay7CntFeature()) {
+      hash = (37 * hash) + VIDEO_DAY7_CNT_FEATURE_FIELD_NUMBER;
+      hash = (53 * hash) + getVideoDay7CntFeature().hashCode();
+    }
+    if (hasVideoMonth3CntFeature()) {
+      hash = (37 * hash) + VIDEO_MONTH3_CNT_FEATURE_FIELD_NUMBER;
+      hash = (53 * hash) + getVideoMonth3CntFeature().hashCode();
+    }
     hash = (29 * hash) + unknownFields.hashCode();
     memoizedHashCode = hash;
     return hash;
@@ -262,6 +812,42 @@ private static final long serialVersionUID = 0L;
     @java.lang.Override
     public Builder clear() {
       super.clear();
+      videoId_ = "";
+
+      upId_ = "";
+
+      tags_ = "";
+
+      playLength_ = "";
+
+      totalTime_ = "";
+
+      daysSinceUpload_ = "";
+
+      if (videoDay1CntFeatureBuilder_ == null) {
+        videoDay1CntFeature_ = null;
+      } else {
+        videoDay1CntFeature_ = null;
+        videoDay1CntFeatureBuilder_ = null;
+      }
+      if (videoDay3CntFeatureBuilder_ == null) {
+        videoDay3CntFeature_ = null;
+      } else {
+        videoDay3CntFeature_ = null;
+        videoDay3CntFeatureBuilder_ = null;
+      }
+      if (videoDay7CntFeatureBuilder_ == null) {
+        videoDay7CntFeature_ = null;
+      } else {
+        videoDay7CntFeature_ = null;
+        videoDay7CntFeatureBuilder_ = null;
+      }
+      if (videoMonth3CntFeatureBuilder_ == null) {
+        videoMonth3CntFeature_ = null;
+      } else {
+        videoMonth3CntFeature_ = null;
+        videoMonth3CntFeatureBuilder_ = null;
+      }
       return this;
     }
 
@@ -288,6 +874,32 @@ private static final long serialVersionUID = 0L;
     @java.lang.Override
     public com.tzld.piaoquan.recommend.feature.model.feature.VideoFeatureProto buildPartial() {
       com.tzld.piaoquan.recommend.feature.model.feature.VideoFeatureProto result = new com.tzld.piaoquan.recommend.feature.model.feature.VideoFeatureProto(this);
+      result.videoId_ = videoId_;
+      result.upId_ = upId_;
+      result.tags_ = tags_;
+      result.playLength_ = playLength_;
+      result.totalTime_ = totalTime_;
+      result.daysSinceUpload_ = daysSinceUpload_;
+      if (videoDay1CntFeatureBuilder_ == null) {
+        result.videoDay1CntFeature_ = videoDay1CntFeature_;
+      } else {
+        result.videoDay1CntFeature_ = videoDay1CntFeatureBuilder_.build();
+      }
+      if (videoDay3CntFeatureBuilder_ == null) {
+        result.videoDay3CntFeature_ = videoDay3CntFeature_;
+      } else {
+        result.videoDay3CntFeature_ = videoDay3CntFeatureBuilder_.build();
+      }
+      if (videoDay7CntFeatureBuilder_ == null) {
+        result.videoDay7CntFeature_ = videoDay7CntFeature_;
+      } else {
+        result.videoDay7CntFeature_ = videoDay7CntFeatureBuilder_.build();
+      }
+      if (videoMonth3CntFeatureBuilder_ == null) {
+        result.videoMonth3CntFeature_ = videoMonth3CntFeature_;
+      } else {
+        result.videoMonth3CntFeature_ = videoMonth3CntFeatureBuilder_.build();
+      }
       onBuilt();
       return result;
     }
@@ -336,6 +948,42 @@ private static final long serialVersionUID = 0L;
 
     public Builder mergeFrom(com.tzld.piaoquan.recommend.feature.model.feature.VideoFeatureProto other) {
       if (other == com.tzld.piaoquan.recommend.feature.model.feature.VideoFeatureProto.getDefaultInstance()) return this;
+      if (!other.getVideoId().isEmpty()) {
+        videoId_ = other.videoId_;
+        onChanged();
+      }
+      if (!other.getUpId().isEmpty()) {
+        upId_ = other.upId_;
+        onChanged();
+      }
+      if (!other.getTags().isEmpty()) {
+        tags_ = other.tags_;
+        onChanged();
+      }
+      if (!other.getPlayLength().isEmpty()) {
+        playLength_ = other.playLength_;
+        onChanged();
+      }
+      if (!other.getTotalTime().isEmpty()) {
+        totalTime_ = other.totalTime_;
+        onChanged();
+      }
+      if (!other.getDaysSinceUpload().isEmpty()) {
+        daysSinceUpload_ = other.daysSinceUpload_;
+        onChanged();
+      }
+      if (other.hasVideoDay1CntFeature()) {
+        mergeVideoDay1CntFeature(other.getVideoDay1CntFeature());
+      }
+      if (other.hasVideoDay3CntFeature()) {
+        mergeVideoDay3CntFeature(other.getVideoDay3CntFeature());
+      }
+      if (other.hasVideoDay7CntFeature()) {
+        mergeVideoDay7CntFeature(other.getVideoDay7CntFeature());
+      }
+      if (other.hasVideoMonth3CntFeature()) {
+        mergeVideoMonth3CntFeature(other.getVideoMonth3CntFeature());
+      }
       this.mergeUnknownFields(other.unknownFields);
       onChanged();
       return this;
@@ -364,6 +1012,938 @@ private static final long serialVersionUID = 0L;
       }
       return this;
     }
+
+    private java.lang.Object videoId_ = "";
+    /**
+     * <code>string video_id = 1;</code>
+     * @return The videoId.
+     */
+    public java.lang.String getVideoId() {
+      java.lang.Object ref = videoId_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        videoId_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string video_id = 1;</code>
+     * @return The bytes for videoId.
+     */
+    public com.google.protobuf.ByteString
+        getVideoIdBytes() {
+      java.lang.Object ref = videoId_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        videoId_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string video_id = 1;</code>
+     * @param value The videoId to set.
+     * @return This builder for chaining.
+     */
+    public Builder setVideoId(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      videoId_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string video_id = 1;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearVideoId() {
+      
+      videoId_ = getDefaultInstance().getVideoId();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string video_id = 1;</code>
+     * @param value The bytes for videoId to set.
+     * @return This builder for chaining.
+     */
+    public Builder setVideoIdBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      videoId_ = value;
+      onChanged();
+      return this;
+    }
+
+    private java.lang.Object upId_ = "";
+    /**
+     * <code>string up_id = 2;</code>
+     * @return The upId.
+     */
+    public java.lang.String getUpId() {
+      java.lang.Object ref = upId_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        upId_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string up_id = 2;</code>
+     * @return The bytes for upId.
+     */
+    public com.google.protobuf.ByteString
+        getUpIdBytes() {
+      java.lang.Object ref = upId_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        upId_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string up_id = 2;</code>
+     * @param value The upId to set.
+     * @return This builder for chaining.
+     */
+    public Builder setUpId(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      upId_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string up_id = 2;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearUpId() {
+      
+      upId_ = getDefaultInstance().getUpId();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string up_id = 2;</code>
+     * @param value The bytes for upId to set.
+     * @return This builder for chaining.
+     */
+    public Builder setUpIdBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      upId_ = value;
+      onChanged();
+      return this;
+    }
+
+    private java.lang.Object tags_ = "";
+    /**
+     * <code>string tags = 3;</code>
+     * @return The tags.
+     */
+    public java.lang.String getTags() {
+      java.lang.Object ref = tags_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        tags_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string tags = 3;</code>
+     * @return The bytes for tags.
+     */
+    public com.google.protobuf.ByteString
+        getTagsBytes() {
+      java.lang.Object ref = tags_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        tags_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string tags = 3;</code>
+     * @param value The tags to set.
+     * @return This builder for chaining.
+     */
+    public Builder setTags(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      tags_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string tags = 3;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearTags() {
+      
+      tags_ = getDefaultInstance().getTags();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string tags = 3;</code>
+     * @param value The bytes for tags to set.
+     * @return This builder for chaining.
+     */
+    public Builder setTagsBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      tags_ = value;
+      onChanged();
+      return this;
+    }
+
+    private java.lang.Object playLength_ = "";
+    /**
+     * <code>string play_length = 4;</code>
+     * @return The playLength.
+     */
+    public java.lang.String getPlayLength() {
+      java.lang.Object ref = playLength_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        playLength_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string play_length = 4;</code>
+     * @return The bytes for playLength.
+     */
+    public com.google.protobuf.ByteString
+        getPlayLengthBytes() {
+      java.lang.Object ref = playLength_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        playLength_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string play_length = 4;</code>
+     * @param value The playLength to set.
+     * @return This builder for chaining.
+     */
+    public Builder setPlayLength(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      playLength_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string play_length = 4;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearPlayLength() {
+      
+      playLength_ = getDefaultInstance().getPlayLength();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string play_length = 4;</code>
+     * @param value The bytes for playLength to set.
+     * @return This builder for chaining.
+     */
+    public Builder setPlayLengthBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      playLength_ = value;
+      onChanged();
+      return this;
+    }
+
+    private java.lang.Object totalTime_ = "";
+    /**
+     * <code>string total_time = 5;</code>
+     * @return The totalTime.
+     */
+    public java.lang.String getTotalTime() {
+      java.lang.Object ref = totalTime_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        totalTime_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string total_time = 5;</code>
+     * @return The bytes for totalTime.
+     */
+    public com.google.protobuf.ByteString
+        getTotalTimeBytes() {
+      java.lang.Object ref = totalTime_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        totalTime_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string total_time = 5;</code>
+     * @param value The totalTime to set.
+     * @return This builder for chaining.
+     */
+    public Builder setTotalTime(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      totalTime_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string total_time = 5;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearTotalTime() {
+      
+      totalTime_ = getDefaultInstance().getTotalTime();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string total_time = 5;</code>
+     * @param value The bytes for totalTime to set.
+     * @return This builder for chaining.
+     */
+    public Builder setTotalTimeBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      totalTime_ = value;
+      onChanged();
+      return this;
+    }
+
+    private java.lang.Object daysSinceUpload_ = "";
+    /**
+     * <code>string days_since_upload = 6;</code>
+     * @return The daysSinceUpload.
+     */
+    public java.lang.String getDaysSinceUpload() {
+      java.lang.Object ref = daysSinceUpload_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        daysSinceUpload_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string days_since_upload = 6;</code>
+     * @return The bytes for daysSinceUpload.
+     */
+    public com.google.protobuf.ByteString
+        getDaysSinceUploadBytes() {
+      java.lang.Object ref = daysSinceUpload_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        daysSinceUpload_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string days_since_upload = 6;</code>
+     * @param value The daysSinceUpload to set.
+     * @return This builder for chaining.
+     */
+    public Builder setDaysSinceUpload(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      daysSinceUpload_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string days_since_upload = 6;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearDaysSinceUpload() {
+      
+      daysSinceUpload_ = getDefaultInstance().getDaysSinceUpload();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string days_since_upload = 6;</code>
+     * @param value The bytes for daysSinceUpload to set.
+     * @return This builder for chaining.
+     */
+    public Builder setDaysSinceUploadBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      daysSinceUpload_ = value;
+      onChanged();
+      return this;
+    }
+
+    private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto videoDay1CntFeature_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> videoDay1CntFeatureBuilder_;
+    /**
+     * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+     * @return Whether the videoDay1CntFeature field is set.
+     */
+    public boolean hasVideoDay1CntFeature() {
+      return videoDay1CntFeatureBuilder_ != null || videoDay1CntFeature_ != null;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+     * @return The videoDay1CntFeature.
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoDay1CntFeature() {
+      if (videoDay1CntFeatureBuilder_ == null) {
+        return videoDay1CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoDay1CntFeature_;
+      } else {
+        return videoDay1CntFeatureBuilder_.getMessage();
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+     */
+    public Builder setVideoDay1CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (videoDay1CntFeatureBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        videoDay1CntFeature_ = value;
+        onChanged();
+      } else {
+        videoDay1CntFeatureBuilder_.setMessage(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+     */
+    public Builder setVideoDay1CntFeature(
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder builderForValue) {
+      if (videoDay1CntFeatureBuilder_ == null) {
+        videoDay1CntFeature_ = builderForValue.build();
+        onChanged();
+      } else {
+        videoDay1CntFeatureBuilder_.setMessage(builderForValue.build());
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+     */
+    public Builder mergeVideoDay1CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (videoDay1CntFeatureBuilder_ == null) {
+        if (videoDay1CntFeature_ != null) {
+          videoDay1CntFeature_ =
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.newBuilder(videoDay1CntFeature_).mergeFrom(value).buildPartial();
+        } else {
+          videoDay1CntFeature_ = value;
+        }
+        onChanged();
+      } else {
+        videoDay1CntFeatureBuilder_.mergeFrom(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+     */
+    public Builder clearVideoDay1CntFeature() {
+      if (videoDay1CntFeatureBuilder_ == null) {
+        videoDay1CntFeature_ = null;
+        onChanged();
+      } else {
+        videoDay1CntFeature_ = null;
+        videoDay1CntFeatureBuilder_ = null;
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder getVideoDay1CntFeatureBuilder() {
+      
+      onChanged();
+      return getVideoDay1CntFeatureFieldBuilder().getBuilder();
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoDay1CntFeatureOrBuilder() {
+      if (videoDay1CntFeatureBuilder_ != null) {
+        return videoDay1CntFeatureBuilder_.getMessageOrBuilder();
+      } else {
+        return videoDay1CntFeature_ == null ?
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoDay1CntFeature_;
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> 
+        getVideoDay1CntFeatureFieldBuilder() {
+      if (videoDay1CntFeatureBuilder_ == null) {
+        videoDay1CntFeatureBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder>(
+                getVideoDay1CntFeature(),
+                getParentForChildren(),
+                isClean());
+        videoDay1CntFeature_ = null;
+      }
+      return videoDay1CntFeatureBuilder_;
+    }
+
+    private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto videoDay3CntFeature_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> videoDay3CntFeatureBuilder_;
+    /**
+     * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+     * @return Whether the videoDay3CntFeature field is set.
+     */
+    public boolean hasVideoDay3CntFeature() {
+      return videoDay3CntFeatureBuilder_ != null || videoDay3CntFeature_ != null;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+     * @return The videoDay3CntFeature.
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoDay3CntFeature() {
+      if (videoDay3CntFeatureBuilder_ == null) {
+        return videoDay3CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoDay3CntFeature_;
+      } else {
+        return videoDay3CntFeatureBuilder_.getMessage();
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+     */
+    public Builder setVideoDay3CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (videoDay3CntFeatureBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        videoDay3CntFeature_ = value;
+        onChanged();
+      } else {
+        videoDay3CntFeatureBuilder_.setMessage(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+     */
+    public Builder setVideoDay3CntFeature(
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder builderForValue) {
+      if (videoDay3CntFeatureBuilder_ == null) {
+        videoDay3CntFeature_ = builderForValue.build();
+        onChanged();
+      } else {
+        videoDay3CntFeatureBuilder_.setMessage(builderForValue.build());
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+     */
+    public Builder mergeVideoDay3CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (videoDay3CntFeatureBuilder_ == null) {
+        if (videoDay3CntFeature_ != null) {
+          videoDay3CntFeature_ =
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.newBuilder(videoDay3CntFeature_).mergeFrom(value).buildPartial();
+        } else {
+          videoDay3CntFeature_ = value;
+        }
+        onChanged();
+      } else {
+        videoDay3CntFeatureBuilder_.mergeFrom(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+     */
+    public Builder clearVideoDay3CntFeature() {
+      if (videoDay3CntFeatureBuilder_ == null) {
+        videoDay3CntFeature_ = null;
+        onChanged();
+      } else {
+        videoDay3CntFeature_ = null;
+        videoDay3CntFeatureBuilder_ = null;
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder getVideoDay3CntFeatureBuilder() {
+      
+      onChanged();
+      return getVideoDay3CntFeatureFieldBuilder().getBuilder();
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoDay3CntFeatureOrBuilder() {
+      if (videoDay3CntFeatureBuilder_ != null) {
+        return videoDay3CntFeatureBuilder_.getMessageOrBuilder();
+      } else {
+        return videoDay3CntFeature_ == null ?
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoDay3CntFeature_;
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> 
+        getVideoDay3CntFeatureFieldBuilder() {
+      if (videoDay3CntFeatureBuilder_ == null) {
+        videoDay3CntFeatureBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder>(
+                getVideoDay3CntFeature(),
+                getParentForChildren(),
+                isClean());
+        videoDay3CntFeature_ = null;
+      }
+      return videoDay3CntFeatureBuilder_;
+    }
+
+    private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto videoDay7CntFeature_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> videoDay7CntFeatureBuilder_;
+    /**
+     * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+     * @return Whether the videoDay7CntFeature field is set.
+     */
+    public boolean hasVideoDay7CntFeature() {
+      return videoDay7CntFeatureBuilder_ != null || videoDay7CntFeature_ != null;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+     * @return The videoDay7CntFeature.
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoDay7CntFeature() {
+      if (videoDay7CntFeatureBuilder_ == null) {
+        return videoDay7CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoDay7CntFeature_;
+      } else {
+        return videoDay7CntFeatureBuilder_.getMessage();
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+     */
+    public Builder setVideoDay7CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (videoDay7CntFeatureBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        videoDay7CntFeature_ = value;
+        onChanged();
+      } else {
+        videoDay7CntFeatureBuilder_.setMessage(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+     */
+    public Builder setVideoDay7CntFeature(
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder builderForValue) {
+      if (videoDay7CntFeatureBuilder_ == null) {
+        videoDay7CntFeature_ = builderForValue.build();
+        onChanged();
+      } else {
+        videoDay7CntFeatureBuilder_.setMessage(builderForValue.build());
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+     */
+    public Builder mergeVideoDay7CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (videoDay7CntFeatureBuilder_ == null) {
+        if (videoDay7CntFeature_ != null) {
+          videoDay7CntFeature_ =
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.newBuilder(videoDay7CntFeature_).mergeFrom(value).buildPartial();
+        } else {
+          videoDay7CntFeature_ = value;
+        }
+        onChanged();
+      } else {
+        videoDay7CntFeatureBuilder_.mergeFrom(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+     */
+    public Builder clearVideoDay7CntFeature() {
+      if (videoDay7CntFeatureBuilder_ == null) {
+        videoDay7CntFeature_ = null;
+        onChanged();
+      } else {
+        videoDay7CntFeature_ = null;
+        videoDay7CntFeatureBuilder_ = null;
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder getVideoDay7CntFeatureBuilder() {
+      
+      onChanged();
+      return getVideoDay7CntFeatureFieldBuilder().getBuilder();
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoDay7CntFeatureOrBuilder() {
+      if (videoDay7CntFeatureBuilder_ != null) {
+        return videoDay7CntFeatureBuilder_.getMessageOrBuilder();
+      } else {
+        return videoDay7CntFeature_ == null ?
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoDay7CntFeature_;
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> 
+        getVideoDay7CntFeatureFieldBuilder() {
+      if (videoDay7CntFeatureBuilder_ == null) {
+        videoDay7CntFeatureBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder>(
+                getVideoDay7CntFeature(),
+                getParentForChildren(),
+                isClean());
+        videoDay7CntFeature_ = null;
+      }
+      return videoDay7CntFeatureBuilder_;
+    }
+
+    private com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto videoMonth3CntFeature_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> videoMonth3CntFeatureBuilder_;
+    /**
+     * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+     * @return Whether the videoMonth3CntFeature field is set.
+     */
+    public boolean hasVideoMonth3CntFeature() {
+      return videoMonth3CntFeatureBuilder_ != null || videoMonth3CntFeature_ != null;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+     * @return The videoMonth3CntFeature.
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoMonth3CntFeature() {
+      if (videoMonth3CntFeatureBuilder_ == null) {
+        return videoMonth3CntFeature_ == null ? com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoMonth3CntFeature_;
+      } else {
+        return videoMonth3CntFeatureBuilder_.getMessage();
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+     */
+    public Builder setVideoMonth3CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (videoMonth3CntFeatureBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        videoMonth3CntFeature_ = value;
+        onChanged();
+      } else {
+        videoMonth3CntFeatureBuilder_.setMessage(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+     */
+    public Builder setVideoMonth3CntFeature(
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder builderForValue) {
+      if (videoMonth3CntFeatureBuilder_ == null) {
+        videoMonth3CntFeature_ = builderForValue.build();
+        onChanged();
+      } else {
+        videoMonth3CntFeatureBuilder_.setMessage(builderForValue.build());
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+     */
+    public Builder mergeVideoMonth3CntFeature(com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto value) {
+      if (videoMonth3CntFeatureBuilder_ == null) {
+        if (videoMonth3CntFeature_ != null) {
+          videoMonth3CntFeature_ =
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.newBuilder(videoMonth3CntFeature_).mergeFrom(value).buildPartial();
+        } else {
+          videoMonth3CntFeature_ = value;
+        }
+        onChanged();
+      } else {
+        videoMonth3CntFeatureBuilder_.mergeFrom(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+     */
+    public Builder clearVideoMonth3CntFeature() {
+      if (videoMonth3CntFeatureBuilder_ == null) {
+        videoMonth3CntFeature_ = null;
+        onChanged();
+      } else {
+        videoMonth3CntFeature_ = null;
+        videoMonth3CntFeatureBuilder_ = null;
+      }
+
+      return this;
+    }
+    /**
+     * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder getVideoMonth3CntFeatureBuilder() {
+      
+      onChanged();
+      return getVideoMonth3CntFeatureFieldBuilder().getBuilder();
+    }
+    /**
+     * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+     */
+    public com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoMonth3CntFeatureOrBuilder() {
+      if (videoMonth3CntFeatureBuilder_ != null) {
+        return videoMonth3CntFeatureBuilder_.getMessageOrBuilder();
+      } else {
+        return videoMonth3CntFeature_ == null ?
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.getDefaultInstance() : videoMonth3CntFeature_;
+      }
+    }
+    /**
+     * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder> 
+        getVideoMonth3CntFeatureFieldBuilder() {
+      if (videoMonth3CntFeatureBuilder_ == null) {
+        videoMonth3CntFeatureBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+            com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto.Builder, com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder>(
+                getVideoMonth3CntFeature(),
+                getParentForChildren(),
+                isClean());
+        videoMonth3CntFeature_ = null;
+      }
+      return videoMonth3CntFeatureBuilder_;
+    }
     @java.lang.Override
     public final Builder setUnknownFields(
         final com.google.protobuf.UnknownFieldSet unknownFields) {

+ 132 - 0
recommend-feature-client/src/main/java/com/tzld/piaoquan/recommend/feature/model/feature/VideoFeatureProtoOrBuilder.java

@@ -6,4 +6,136 @@ package com.tzld.piaoquan.recommend.feature.model.feature;
 public interface VideoFeatureProtoOrBuilder extends
     // @@protoc_insertion_point(interface_extends:VideoFeatureProto)
     com.google.protobuf.MessageOrBuilder {
+
+  /**
+   * <code>string video_id = 1;</code>
+   * @return The videoId.
+   */
+  java.lang.String getVideoId();
+  /**
+   * <code>string video_id = 1;</code>
+   * @return The bytes for videoId.
+   */
+  com.google.protobuf.ByteString
+      getVideoIdBytes();
+
+  /**
+   * <code>string up_id = 2;</code>
+   * @return The upId.
+   */
+  java.lang.String getUpId();
+  /**
+   * <code>string up_id = 2;</code>
+   * @return The bytes for upId.
+   */
+  com.google.protobuf.ByteString
+      getUpIdBytes();
+
+  /**
+   * <code>string tags = 3;</code>
+   * @return The tags.
+   */
+  java.lang.String getTags();
+  /**
+   * <code>string tags = 3;</code>
+   * @return The bytes for tags.
+   */
+  com.google.protobuf.ByteString
+      getTagsBytes();
+
+  /**
+   * <code>string play_length = 4;</code>
+   * @return The playLength.
+   */
+  java.lang.String getPlayLength();
+  /**
+   * <code>string play_length = 4;</code>
+   * @return The bytes for playLength.
+   */
+  com.google.protobuf.ByteString
+      getPlayLengthBytes();
+
+  /**
+   * <code>string total_time = 5;</code>
+   * @return The totalTime.
+   */
+  java.lang.String getTotalTime();
+  /**
+   * <code>string total_time = 5;</code>
+   * @return The bytes for totalTime.
+   */
+  com.google.protobuf.ByteString
+      getTotalTimeBytes();
+
+  /**
+   * <code>string days_since_upload = 6;</code>
+   * @return The daysSinceUpload.
+   */
+  java.lang.String getDaysSinceUpload();
+  /**
+   * <code>string days_since_upload = 6;</code>
+   * @return The bytes for daysSinceUpload.
+   */
+  com.google.protobuf.ByteString
+      getDaysSinceUploadBytes();
+
+  /**
+   * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+   * @return Whether the videoDay1CntFeature field is set.
+   */
+  boolean hasVideoDay1CntFeature();
+  /**
+   * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+   * @return The videoDay1CntFeature.
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoDay1CntFeature();
+  /**
+   * <code>.UserActionFeatureProto video_day1_cnt_feature = 7;</code>
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoDay1CntFeatureOrBuilder();
+
+  /**
+   * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+   * @return Whether the videoDay3CntFeature field is set.
+   */
+  boolean hasVideoDay3CntFeature();
+  /**
+   * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+   * @return The videoDay3CntFeature.
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoDay3CntFeature();
+  /**
+   * <code>.UserActionFeatureProto video_day3_cnt_feature = 8;</code>
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoDay3CntFeatureOrBuilder();
+
+  /**
+   * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+   * @return Whether the videoDay7CntFeature field is set.
+   */
+  boolean hasVideoDay7CntFeature();
+  /**
+   * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+   * @return The videoDay7CntFeature.
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoDay7CntFeature();
+  /**
+   * <code>.UserActionFeatureProto video_day7_cnt_feature = 9;</code>
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoDay7CntFeatureOrBuilder();
+
+  /**
+   * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+   * @return Whether the videoMonth3CntFeature field is set.
+   */
+  boolean hasVideoMonth3CntFeature();
+  /**
+   * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+   * @return The videoMonth3CntFeature.
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto getVideoMonth3CntFeature();
+  /**
+   * <code>.UserActionFeatureProto video_month3_cnt_feature = 10;</code>
+   */
+  com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProtoOrBuilder getVideoMonth3CntFeatureOrBuilder();
 }

+ 32 - 1
recommend-feature-client/src/main/proto/com/tzld/piaoquan/recommend/feature/feature.proto

@@ -18,11 +18,22 @@ message GetUserFeatureResponse {
 }
 
 message UserFeatureProto {
+  string mid = 1;
+  string uid = 2;
+
+  UserActionFeatureProto day1_cnt_feature = 3;
+  UserActionFeatureProto day3_cnt_feature = 4;
+  UserActionFeatureProto day7_cnt_feature = 5;
+  UserActionFeatureProto month3_cnt_feature = 6;
+
+  string user_cycle_bucket_7day = 7;
+  string user_cycle_bucket_30day = 8;
+  string user_share_bucket_30day = 9;
 
 }
 
 message GetVideoFeatureRequest {
-  int64 video_id = 1;
+  string video_id = 1;
 }
 
 message GetVideoFeatureResponse {
@@ -31,6 +42,26 @@ message GetVideoFeatureResponse {
 }
 
 message VideoFeatureProto {
+  string video_id = 1;
+  string up_id = 2;
+  string tags = 3;
+  string play_length = 4;
+  string total_time = 5;
+  string days_since_upload = 6;
+  UserActionFeatureProto video_day1_cnt_feature = 7;
+  UserActionFeatureProto video_day3_cnt_feature = 8;
+  UserActionFeatureProto video_day7_cnt_feature = 9;
+  UserActionFeatureProto video_month3_cnt_feature = 10;
+}
+
+message UserActionFeatureProto{
+  int64 exp_cnt = 1;
+  int64 click_cnt = 2;
+  int64 share_cnt = 3;
+  int64 return_cnt = 4;
+  double  ctr = 5;
+  double  str = 6;
+  double  rov = 7;
 
 }
 

+ 10 - 1
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/model/UserActionFeature.java

@@ -1,8 +1,17 @@
 package com.tzld.piaoquan.recommend.feature.model;
 
+import lombok.Data;
+
 /**
  * @author dyp
  */
+@Data
 public class UserActionFeature {
-    private String uid;
+    private long expCnt;
+    private long clickCnt;
+    private long shareCnt;
+    private long returnCnt;
+    private double ctr;
+    private double str;
+    private double rov;
 }

+ 13 - 0
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/model/UserFeature.java

@@ -7,5 +7,18 @@ import lombok.Data;
  */
 @Data
 public class UserFeature {
+    private String mid;
     private String uid;
+    // 当天统计量信息
+    private UserActionFeature day1CntFeature;
+    // 3天内统计量
+    private UserActionFeature day3CntFeature;
+    // 7天内统计量
+    private UserActionFeature day7CntFeature;
+    // 3个月统计量
+    private UserActionFeature month3CntFeature;
+    // 用户行为周期
+    private String userCycleBucket7days;
+    private String userCycleBucket30days;
+    private String userShareBucket30days;
 }

+ 15 - 1
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/model/VideoFeature.java

@@ -7,5 +7,19 @@ import lombok.Data;
  */
 @Data
 public class VideoFeature {
-    private Long videoId;
+    private String videoId;
+    private String upId;
+    private String tags;
+    private String playLength;
+    private String totalTime;
+    private String daysSinceUpload;
+
+    // 当天统计量信息
+    private UserActionFeature videoDay1CntFeature;
+    // 3天内统计量
+    private UserActionFeature videoDay3CntFeature;
+    // 7天内统计量
+    private UserActionFeature videoDay7CntFeature;
+    // 3个月统计量
+    private UserActionFeature videoMonth3CntFeature;
 }

+ 60 - 0
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/service/FeatureConverter.java

@@ -0,0 +1,60 @@
+package com.tzld.piaoquan.recommend.feature.service;
+
+import com.google.common.base.Strings;
+import com.tzld.piaoquan.recommend.feature.model.UserActionFeature;
+import com.tzld.piaoquan.recommend.feature.model.UserFeature;
+import com.tzld.piaoquan.recommend.feature.model.VideoFeature;
+import com.tzld.piaoquan.recommend.feature.model.feature.UserActionFeatureProto;
+import com.tzld.piaoquan.recommend.feature.model.feature.UserFeatureProto;
+import com.tzld.piaoquan.recommend.feature.model.feature.VideoFeatureProto;
+
+/**
+ * @author dyp
+ */
+public class FeatureConverter {
+    public static UserFeatureProto convert(UserFeature userFeature) {
+        UserFeatureProto.Builder builder = UserFeatureProto.newBuilder();
+        builder.setMid(Strings.nullToEmpty(userFeature.getMid()))
+                .setUid(Strings.nullToEmpty(userFeature.getUid()))
+                .setUserCycleBucket7Day(Strings.nullToEmpty(userFeature.getUserCycleBucket7days()))
+                .setUserCycleBucket30Day(Strings.nullToEmpty(userFeature.getUserCycleBucket30days()))
+                .setUserShareBucket30Day(Strings.nullToEmpty(userFeature.getUserShareBucket30days()))
+                .setDay1CntFeature(convert(userFeature.getDay1CntFeature()))
+                .setDay3CntFeature(convert(userFeature.getDay3CntFeature()))
+                .setDay7CntFeature(convert(userFeature.getDay7CntFeature()))
+                .setMonth3CntFeature(convert(userFeature.getMonth3CntFeature()));
+        return builder.build();
+    }
+
+    private static UserActionFeatureProto convert(UserActionFeature feature) {
+        UserActionFeatureProto.Builder builder = UserActionFeatureProto.newBuilder();
+        builder.setCtr(feature.getCtr())
+                .setStr(feature.getStr())
+                .setRov(feature.getRov())
+                .setShareCnt(feature.getShareCnt())
+                .setReturnCnt(feature.getReturnCnt())
+                .setClickCnt(feature.getClickCnt())
+                .setExpCnt(feature.getExpCnt());
+
+        return builder.build();
+    }
+
+
+    public static VideoFeatureProto convert(VideoFeature videoFeature) {
+        VideoFeatureProto.Builder builder = VideoFeatureProto.newBuilder();
+
+        builder.setVideoId(Strings.nullToEmpty(videoFeature.getVideoId()))
+                .setUpId(Strings.nullToEmpty(videoFeature.getUpId()))
+                .setTags(Strings.nullToEmpty(videoFeature.getTags()))
+                .setPlayLength(Strings.nullToEmpty(videoFeature.getPlayLength()))
+                .setTotalTime(Strings.nullToEmpty(videoFeature.getTotalTime()))
+                .setDaysSinceUpload(Strings.nullToEmpty(videoFeature.getDaysSinceUpload()))
+                .setVideoDay1CntFeature(convert(videoFeature.getVideoDay1CntFeature()))
+                .setVideoDay3CntFeature(convert(videoFeature.getVideoDay3CntFeature()))
+                .setVideoDay7CntFeature(convert(videoFeature.getVideoDay7CntFeature()))
+                .setVideoMonth3CntFeature(convert(videoFeature.getVideoMonth3CntFeature()));
+
+        // TODO
+        return builder.build();
+    }
+}

+ 2 - 10
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/service/UserFeatureService.java

@@ -5,7 +5,6 @@ import com.tzld.piaoquan.recommend.feature.model.UserFeature;
 import com.tzld.piaoquan.recommend.feature.model.common.Result;
 import com.tzld.piaoquan.recommend.feature.model.feature.GetUserFeatureRequest;
 import com.tzld.piaoquan.recommend.feature.model.feature.GetUserFeatureResponse;
-import com.tzld.piaoquan.recommend.feature.model.feature.UserFeatureProto;
 import com.tzld.piaoquan.recommend.feature.util.JSONUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
@@ -22,7 +21,7 @@ public class UserFeatureService extends AbstractFeatureService<String, UserFeatu
         super.emptyData = "{}";
         super.emptyDataExpire = 60;
         super.defaultExpire = 7200;
-        super.keyFunc = k -> String.format("video:meta:%s", k);
+        super.keyFunc = k -> String.format("user:meta:%s", k);
         super.typeToken = new TypeToken<UserFeature>() {
         };
 
@@ -44,17 +43,10 @@ public class UserFeatureService extends AbstractFeatureService<String, UserFeatu
         UserFeature userFeature = super.get(uid);
         return GetUserFeatureResponse.newBuilder()
                 .setResult(Result.newBuilder().setCode(1))
-                .setUserFeature(convert(userFeature))
+                .setUserFeature(FeatureConverter.convert(userFeature))
                 .build();
     }
 
-    private UserFeatureProto convert(UserFeature userFeature) {
-        UserFeatureProto.Builder builder = UserFeatureProto.newBuilder();
-
-        // TODO
-        return builder.build();
-    }
-
     public void saveUserFeature(String jsonValue) {
 
         UserFeature userFeature = JSONUtils.fromJson(jsonValue, new TypeToken<UserFeature>() {

+ 5 - 12
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/service/VideoFeatureService.java

@@ -5,9 +5,9 @@ import com.tzld.piaoquan.recommend.feature.model.VideoFeature;
 import com.tzld.piaoquan.recommend.feature.model.common.Result;
 import com.tzld.piaoquan.recommend.feature.model.feature.GetVideoFeatureRequest;
 import com.tzld.piaoquan.recommend.feature.model.feature.GetVideoFeatureResponse;
-import com.tzld.piaoquan.recommend.feature.model.feature.VideoFeatureProto;
 import com.tzld.piaoquan.recommend.feature.util.JSONUtils;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
 import org.springframework.stereotype.Service;
 
 /**
@@ -15,7 +15,7 @@ import org.springframework.stereotype.Service;
  */
 @Service
 @Slf4j
-public class VideoFeatureService extends AbstractFeatureService<Long, VideoFeature> {
+public class VideoFeatureService extends AbstractFeatureService<String, VideoFeature> {
 
     public VideoFeatureService() {
         super.emptyData = "{}";
@@ -34,8 +34,8 @@ public class VideoFeatureService extends AbstractFeatureService<Long, VideoFeatu
 
 
     public GetVideoFeatureResponse getVideoFeature(GetVideoFeatureRequest request) {
-        long videoId = request.getVideoId();
-        if (videoId == 0) {
+        String videoId = request.getVideoId();
+        if (StringUtils.isBlank(videoId)) {
             return GetVideoFeatureResponse.newBuilder()
                     .setResult(Result.newBuilder().setCode(1))
                     .build();
@@ -43,17 +43,10 @@ public class VideoFeatureService extends AbstractFeatureService<Long, VideoFeatu
         VideoFeature videoFeature = super.get(videoId);
         return GetVideoFeatureResponse.newBuilder()
                 .setResult(Result.newBuilder().setCode(1))
-                .setVideoFeature(convert(videoFeature))
+                .setVideoFeature(FeatureConverter.convert(videoFeature))
                 .build();
     }
 
-    private VideoFeatureProto convert(VideoFeature videoFeature) {
-        VideoFeatureProto.Builder builder = VideoFeatureProto.newBuilder();
-
-        // TODO
-        return builder.build();
-    }
-
     public void saveVideoFeature(String jsonValue) {
 
         VideoFeature videoFeature = JSONUtils.fromJson(jsonValue, new TypeToken<VideoFeature>() {