+ * the AV id is a number; the BV id is a special base58 number, it shows as String in programming.
+ * eg:
+ * while the link {@code https://www.bilibili.com/video/BV17x411w7KC/}
+ * shows the same with {@code https://www.bilibili.com/video/av170001/},
+ * the AV id is {@code 170001}, the BV id is {@code 17x411w7KC}
+ *
+ * for now , the BV id has 10 digits. + * the method available while the av-id < 2^27, while it theoretically available when the av-id < 2^30. + * + * @see mcfx的回复: 如何看待 2020 年 3 月 23 日哔哩哔哩将稿件的「av 号」变更为「BV 号」? + * + * @param bv the BV id, a string in (a special) base58 number format, without "BV" prefix. + * @return the AV id corresponding to this bv id in Bilibili, formatted as a number. + */ + @Nonnegative + public static long toAv (@Nonnull String bv) { + long av = 0; + for (int i = 0; i < BV_TEMPLATE_FILTER.length; i++) { + av += BV_TABLE_REVERSED.get(bv.charAt(BV_TEMPLATE_FILTER[i])) * Math.pow(TABLE_INT,i); + } + return (av-V_CONV_ADD)^V_CONV_XOR; + } + + /** + * Convert a Bilibili BV video id format to AV id format. + *
+ * the AV id is a number; the BV id is a special base58 number, it shows as String in programming.
+ * eg:
+ * while the link {@code https://www.bilibili.com/video/BV17x411w7KC/}
+ * shows the same with {@code https://www.bilibili.com/video/av170001/},
+ * the AV id is {@code 170001}, the BV id is {@code 17x411w7KC}
+ *
+ * for now , the BV id has 10 digits. + * the method available while the av-id < 2^27, while it theoretically available when the av-id < 2^30. + * + * @see mcfx的回复: 如何看待 2020 年 3 月 23 日哔哩哔哩将稿件的「av 号」变更为「BV 号」? + * + * @param av the (base10) AV id. + * @return the AV id corresponding to this bv id in Bilibili, + * as a (special) base 58 number format without "BV" prefix. + */ + @Nonnull + public static String toBv (@Nonnegative long av) { + av = (av^V_CONV_XOR)+V_CONV_ADD; + final char[] bv = BV_TEMPLATE.clone(); + for (int i = 0; i < BV_TEMPLATE_FILTER.length; i++) { + bv[BV_TEMPLATE_FILTER[i]] = BV_TABLE[(int)(Math.floor(av/(Math.pow(TABLE_INT, i)))%TABLE_INT)]; + } + return String.copyValueOf(bv); + } + +} diff --git a/src/test/java/cc/sukazyo/cono/morny/util/TestBiliTool.java b/src/test/java/cc/sukazyo/cono/morny/util/TestBiliTool.java new file mode 100644 index 0000000..125d9c6 --- /dev/null +++ b/src/test/java/cc/sukazyo/cono/morny/util/TestBiliTool.java @@ -0,0 +1,30 @@ +package cc.sukazyo.cono.morny.util; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static cc.sukazyo.cono.morny.util.BiliTool.*; + +public class TestBiliTool { + + private static final String AV_BV_DATA_CSV = """ + 17x411w7KC, 170001 + 1Q541167Qg, 455017605 + 1mK4y1C7Bz, 882584971 + 1T24y197V2, 688730800 + """; + + @ParameterizedTest + @CsvSource(textBlock = AV_BV_DATA_CSV) + void testAvToBv (String bv, int av) { + Assertions.assertEquals(bv, toBv(av)); + } + + @ParameterizedTest + @CsvSource(textBlock = AV_BV_DATA_CSV) + void testBvToAv (String bv, int av) { + Assertions.assertEquals(av, toAv(bv)); + } + +}