• Source
    1.  
    2. import http.client
    3.  
    4. import json
    5.  
    6. import csv
    7.  
    8. import urllib.request
    9.  
    10.  
    11. #############################################################################################################################
    12.  
    13. # cse6242 s21
    14.  
    15. # All instructions, code comments, etc. contained within this notebook are part of the assignment instructions.
    16.  
    17. # Portions of this file will auto-graded in Gradescope using different sets of parameters / data to ensure that values are not
    18.  
    19. # hard-coded.
    20.  
    21. #
    22.  
    23. # Instructions: Implement all methods in this file that have a return
    24.  
    25. # value of 'NotImplemented'. See the documentation within each method for specific details, including
    26.  
    27. # the expected return value
    28.  
    29. #
    30.  
    31. # Helper Functions:
    32.  
    33. # You are permitted to write additional helper functions/methods or use additional instance variables within
    34.  
    35. # the `Graph` class or `TMDbAPIUtils` class so long as the originally included methods work as required.
    36.  
    37. #
    38.  
    39. # Use:
    40.  
    41. # The `Graph` class is used to represent and store the data for the TMDb co-actor network graph. This class must
    42.  
    43. # also provide some basic analytics, i.e., number of nodes, edges, and nodes with the highest degree.
    44.  
    45. #
    46.  
    47. # The `TMDbAPIUtils` class is used to retrieve Actor/Movie data using themoviedb.org API. We have provided a few necessary methods
    48.  
    49. # to test your code w/ the API, e.g.: get_move_detail(), get_movie_cast(), get_movie_credits_for_person(). You may add additional
    50.  
    51. # methods and instance variables as desired (see Helper Functions).
    52.  
    53. #
    54.  
    55. # The data that you retrieve from the TMDb API is used to build your graph using the Graph class. After you build your graph using the
    56.  
    57. # TMDb API data, use the Graph class write_edges_file & write_nodes_file methods to produce the separate nodes and edges
    58.  
    59. # .csv files for use with the Argo-Lite graph visualization tool.
    60.  
    61. #
    62.  
    63. # While building the co-actor graph, you will be required to write code to expand the graph by iterating
    64.  
    65. # through a portion of the graph nodes and finding similar artists using the TMDb API. We will not grade this code directly
    66.  
    67. # but will grade the resulting graph data in your Argo-Lite graph snapshot.
    68.  
    69. #
    70.  
    71. #############################################################################################################################
    72.  
    73.  
    74. class Graph:
    75.  
    76. # Do not modify
    77.  
    78. def __init__(self, with_nodes_file=None, with_edges_file=None):
    79. """
    80.  
    81.  
    82.  
    83. option 1: init as an empty graph and add nodes
    84.  
    85.  
    86.  
    87. option 2: init by specifying a path to nodes & edges files
    88.  
    89.  
    90.  
    91. """
    92.  
    93. self.nodes = []
    94.  
    95. self.edges = []
    96.  
    97. if with_nodes_file and with_edges_file:
    98.  
    99. nodes_CSV = csv.reader(open(with_nodes_file))
    100.  
    101. nodes_CSV = list(nodes_CSV)[1:]
    102.  
    103. self.nodes = [(n[0], n[1]) for n in nodes_CSV]
    104.  
    105. edges_CSV = csv.reader(open(with_edges_file))
    106.  
    107. edges_CSV = list(edges_CSV)[1:]
    108.  
    109. self.edges = [(e[0], e[1]) for e in edges_CSV]
    110.  
    111. def add_node(self, id: str, name: str) -> None:
    112. """
    113.  
    114. add a tuple (id, name) representing a node to self.nodes if it does not already exist
    115.  
    116. The graph should not contain any duplicate nodes
    117.  
    118. """
    119.  
    120. new_node = (id, name)
    121.  
    122. if(new_node not in self.nodes):
    123.  
    124. self.nodes.append(new_node)
    125.  
    126. #init_graph = Graph()
    127.  
    128. #init_graph.add_node(id= '9' , name = 'aaaa')
    129.  
    130. #init_graph.add_node(id= '9' , name = 'aaaa')
    131.  
    132. # print(init_graph.nodes)
    133.  
    134. # return NotImplemented
    135.  
    136. def add_edge(self, source: str, target: str) -> None:
    137. """
    138.  
    139. Add an edge between two nodes if it does not already exist.
    140.  
    141. An edge is represented by a tuple containing two strings: e.g.: ('source', 'target').
    142.  
    143. Where 'source' is the id of the source node and 'target' is the id of the target node
    144.  
    145. e.g., for two nodes with ids 'a' and 'b' respectively, add the tuple ('a', 'b') to self.edges
    146.  
    147. """
    148.  
    149. edge = (source, target)
    150.  
    151. if edge not in self.edges:
    152.  
    153. self.edges.append(edge)
    154.  
    155. # return NotImplemented
    156.  
    157. def total_nodes(self) -> int:
    158. """
    159.  
    160. Returns an integer value for the total number of nodes in the graph
    161.  
    162. """
    163.  
    164. return len(self.nodes)
    165.  
    166. # return NotImplemented
    167.  
    168. def total_edges(self) -> int:
    169. """
    170.  
    171. Returns an integer value for the total number of edges in the graph
    172.  
    173. """
    174.  
    175. return len(self.edges)
    176.  
    177. # return NotImplemented
    178.  
    179. def max_degree_nodes(self) -> dict:
    180. """
    181.  
    182. Return the node(s) with the highest degree
    183.  
    184. Return multiple nodes in the event of a tie
    185.  
    186. Format is a dict where the key is the node_id and the value is an integer for the node degree
    187.  
    188. e.g. {'a': 8}
    189.  
    190. or {'a': 22, 'b': 22}
    191.  
    192. """
    193.  
    194. # degrees = {}
    195.  
    196. # for i in self.edges:
    197.  
    198. # if i[0] not in degrees:
    199.  
    200. # degrees[i[0]] = 1
    201.  
    202. # else:
    203.  
    204. # degrees[i[0]]+=1
    205.  
    206. # max_degree = 0
    207.  
    208. # for val in degrees.values():
    209.  
    210. # if val > max_degree:
    211.  
    212. # max_degree = val
    213.  
    214. # max_degrees_dict = {}
    215.  
    216. # for node in degrees:
    217.  
    218. # if degrees[node] == max_degree:
    219.  
    220. # max_degrees_dict[node] = max_degree
    221.  
    222. # return max_degrees_dict
    223.  
    224. # get count for each node
    225.  
    226. count = {}
    227.  
    228. for edge in self.edges:
    229.  
    230. if(edge[1] not in count):
    231.  
    232. count[edge[1]] = 0
    233.  
    234. count[edge[1]] += 1
    235.  
    236. # get max count
    237.  
    238. max_count = -1
    239.  
    240. for node in count:
    241.  
    242. if(count[node] > max_count):
    243.  
    244. max_count = count[node]
    245.  
    246. # create dict with max
    247.  
    248. nodes = {}
    249.  
    250. for node in count:
    251.  
    252. if (count[node] == max_count):
    253.  
    254. nodes[node] = max_count
    255.  
    256. return nodes
    257.  
    258. # return NotImplemented
    259.  
    260. def print_nodes(self):
    261. """
    262.  
    263. No further implementation required
    264.  
    265. May be used for de-bugging if necessary
    266.  
    267. """
    268.  
    269. print(self.nodes)
    270.  
    271. def print_edges(self):
    272. """
    273.  
    274. No further implementation required
    275.  
    276. May be used for de-bugging if necessary
    277.  
    278. """
    279.  
    280. print(self.edges)
    281.  
    282. # Do not modify
    283.  
    284. def write_edges_file(self, path="edges.csv") -> None:
    285. """
    286.  
    287. write all edges out as .csv
    288.  
    289. :param path: string
    290.  
    291. :return: None
    292.  
    293. """
    294.  
    295. edges_path = path
    296.  
    297. edges_file = open(edges_path, 'w', encoding='utf-8')
    298.  
    299. edges_file.write("source" + "," + "target" + "\n")
    300.  
    301. for e in self.edges:
    302.  
    303. edges_file.write(e[0] + "," + e[1] + "\n")
    304.  
    305. edges_file.close()
    306.  
    307. print("finished writing edges to csv")
    308.  
    309. # Do not modify
    310.  
    311. def write_nodes_file(self, path="nodes.csv") -> None:
    312. """
    313.  
    314. write all nodes out as .csv
    315.  
    316. :param path: string
    317.  
    318. :return: None
    319.  
    320. """
    321.  
    322. nodes_path = path
    323.  
    324. nodes_file = open(nodes_path, 'w', encoding='utf-8')
    325.  
    326. nodes_file.write("id,name" + "\n")
    327.  
    328. for n in self.nodes:
    329.  
    330. nodes_file.write(n[0] + "," + n[1] + "\n")
    331.  
    332. nodes_file.close()
    333.  
    334. print("finished writing nodes to csv")
    335.  
    336.  
    337. class TMDBAPIUtils:
    338.  
    339. movie_Cast_list = []
    340.  
    341. # Do not modify
    342.  
    343. def __init__(self, api_key: str):
    344.  
    345. self.api_key = api_key
    346.  
    347. def get_movie_cast(self, movie_id: str, limit: int = None, exclude_ids: list = None) -> list:
    348. """
    349.  
    350. Get the movie cast for a given movie id, with optional parameters to exclude an cast member
    351.  
    352. from being returned and/or to limit the number of returned cast members
    353.  
    354. documentation url: https://developers.themoviedb.org/3/movies/get-movie-credits
    355.  
    356.  
    357.  
    358. :param integer movie_id: a movie_id
    359.  
    360. :param integer limit: maximum number of returned cast members by their 'order' attribute
    361.  
    362. e.g., limit=5 will attempt to return the 5 cast members having 'order' attribute values between 0-4
    363.  
    364. If after exluding, there are fewer cast members than the specified limit or the limit not specified, return all cast members.
    365.  
    366. If cast members with 'order' attribute in the specified limit range have been excluded, do not include more cast members to reach the limit.
    367.  
    368. e.g., if limit=5 and the actor whose id corresponds to cast member with order=1 is to be excluded,
    369.  
    370. return cast members with order values [0, 2, 3, 4], not [0, 2, 3, 4, 5]
    371.  
    372. :param list exclude_ids: a list of ints containing ids (not cast_ids) of cast members that should be excluded from the returned result
    373.  
    374. e.g., if exclude_ids are [353, 455] then exclude these from any result.
    375.  
    376. :rtype: list
    377.  
    378. return a list of dicts, one dict per cast member with the following structure:
    379.  
    380. [{'cast_id': '97909' # the id of the cast member
    381.  
    382. 'character': 'John Doe' # the name of the character played
    383.  
    384. 'credit_id': '52fe4249c3a36847f8012927' # id of the credit}, ... ]
    385.  
    386. """
    387.  
    388. global movie_Cast_list
    389.  
    390. movie_Cast_list = []
    391.  
    392. global movie_Cast
    393.  
    394. movie_Cast = []
    395.  
    396. global conn
    397.  
    398. # return NotImplemented
    399.  
    400. conn = http.client.HTTPSConnection("api.themoviedb.org")
    401.  
    402. #conn.request("GET", "/3/movie/movie_id/credits?api_key='11cf6e0baa84777c109be80a6cffdab3'".format(movie_id, self.api_key))
    403.  
    404. conn.request(
    405. "GET", "/3/movie/{}/credits?api_key={}".format(movie_id, self.api_key))
    406.  
    407. r1 = conn.getresponse()
    408.  
    409. print(r1.read())
    410.  
    411. print(r1.status, r1.reason)
    412.  
    413. if r1.status == 200:
    414.  
    415. movie_data = r1.read()
    416.  
    417. movie_data_list = json.loads(movie_data.decode('utf-8'))
    418.  
    419. movie_Cast = movie_data_list['cast']
    420.  
    421. ##movie_Cast_list = []
    422.  
    423. for dictat in movie_Cast:
    424.  
    425. # print(dictat)
    426.  
    427. movie_Cast_shrinked = {key_i: dictat[key_i] for key_i in dictat.keys()
    428.  
    429. & {'cast_id', 'character', 'credit_id'}}
    430.  
    431. movie_Cast_list.append(movie_Cast_shrinked)
    432.  
    433. print(movie_Cast_list)
    434. mc_order_filter = []
    435. if exclude_ids and limit:
    436.  
    437. # exlude ids first
    438.  
    439. exclude_ids_ = exclude_ids
    440.  
    441. mc_ID_filter = [
    442. d for d in movie_Cast_list if d['id'] not in exclude_ids_]
    443.  
    444. # select only the records where order is smaller than the limit
    445.  
    446. mc_order_filter = [d for d in mc_ID_filter if d['order'] < limit]
    447.  
    448. # get only certain string from the filtered dict in the list
    449.  
    450. for dictat in mc_order_filter:
    451.  
    452. movie_Cast_shrinked = {key_i: dictat[key_i] for key_i in dictat.keys()
    453.  
    454. & {'cast_id', 'character', 'credit_id'}}
    455.  
    456. movie_Cast_list = movie_Cast_list.append(movie_Cast_shrinked)
    457.  
    458. return movie_Cast_list
    459.  
    460. apiKey = '11cf6e0baa84777c109be80a6cffdab3'
    461.  
    462. tmdb_api_utils = TMDBAPIUtils(apiKey)
    463.  
    464. test_m1 = tmdb_api_utils.get_movie_cast(movie_id='100')
    465.  
    466. print(test_m1)
    467.  
    468. def get_movie_credits_for_person(self, person_id: str, vote_avg_threshold: float = None) -> list:
    469. """
    470.  
    471. Using the TMDb API, get the movie credits for a person serving in a cast role
    472.  
    473. documentation url: https://developers.themoviedb.org/3/people/get-person-movie-credits
    474.  
    475. :param string person_id: the id of a person
    476.  
    477. :param vote_avg_threshold: optional parameter to return the movie credit if it is >=
    478.  
    479. the specified threshold.
    480.  
    481. e.g., if the vote_avg_threshold is 5.0, then only return credits with a vote_avg >= 5.0
    482.  
    483. :rtype: list
    484.  
    485. return a list of dicts, one dict per movie credit with the following structure:
    486.  
    487. [{'id': '97909' # the id of the movie credit
    488.  
    489. 'title': 'Long, Stock and Two Smoking Barrels' # the title (not original title) of the credit
    490.  
    491. 'vote_avg': 5.0 # the float value of the vote average value for the credit}, ... ]
    492.  
    493. """
    494.  
    495. # base_url variable to store url
    496.  
    497. base_url_1 = "https://api.themoviedb.org/3/person/"
    498.  
    499. API_KEY = '11cf6e0baa84777c109be80a6cffdab3'
    500.  
    501. base_url_2 = "/movie_credits?api_key="+API_KEY+"&language=en-US"
    502.  
    503. # Give Personal ID
    504.  
    505. person_id = input("Enter Personal ID: ")
    506.  
    507. vote_avg_threshold = float(input("Enter Vote average: "))
    508.  
    509. # complete url address
    510.  
    511. complete_url = base_url_1+person_id+base_url_2
    512.  
    513. # get method of requests module
    514.  
    515. # return response object
    516.  
    517. req = urllib.request.Request(complete_url)
    518.  
    519. response = urllib.request.urlopen(req).read()
    520.  
    521. # json method of response object
    522.  
    523. # convert json format data into
    524.  
    525. # python format data
    526.  
    527. x = json.loads(response)
    528.  
    529. data = []
    530.  
    531. for movie in x['cast']:
    532.  
    533. if vote_avg_threshold >= movie["vote_average"]:
    534.  
    535. data.append(
    536. {"id": movie["credit_id"], "title": movie["title"], "vote_avg": movie["vote_average"]})
    537.  
    538. return data
    539.  
    540.  
    541. x = TMDBAPIUtils('11cf6e0baa84777c109be80a6cffdab3')
    542.  
    543. print(x.get_movie_credits_for_person('500', 5.0))
    544.  
    545.  
    546. #############################################################################################################################
    547.  
    548. #
    549.  
    550. # BUILDING YOUR GRAPH
    551.  
    552. #
    553.  
    554. # Working with the API: See use of http.request: https://docs.python.org/3/library/http.client.html#examples
    555.  
    556. #
    557.  
    558. # Using TMDb's API, build a co-actor network for the actor's/actress' highest rated movies
    559.  
    560. # In this graph, each node represents an actor
    561.  
    562. # An edge between any two nodes indicates that the two actors/actresses acted in a movie together
    563.  
    564. # i.e., they share a movie credit.
    565.  
    566. # e.g., An edge between Samuel L. Jackson and Robert Downey Jr. indicates that they have acted in one
    567.  
    568. # or more movies together.
    569.  
    570. #
    571.  
    572. # For this assignment, we are interested in a co-actor network of highly rated movies; specifically,
    573.  
    574. # we only want the top 3 co-actors in each movie credit of an actor having a vote average >= 8.0.
    575.  
    576. # Build your co-actor graph on the actor 'Laurence Fishburne' w/ person_id 2975.
    577.  
    578. #
    579.  
    580. # You will need to add extra functions or code to accomplish this. We will not directly call or explicitly grade your
    581.  
    582. # algorithm. We will instead measure the correctness of your output by evaluating the data in your argo-lite graph
    583.  
    584. # snapshot.
    585.  
    586. #
    587.  
    588. # GRAPH SIZE
    589.  
    590. # With each iteration of your graph build, the number of nodes and edges grows approximately at an exponential rate.
    591.  
    592. # Our testing indicates growth approximately equal to e^2x.
    593.  
    594. # Since the TMDB API is a live database, the number of nodes / edges in the final graph will vary slightly depending on when
    595.  
    596. # you execute your graph building code. We take this into account by rebuilding the solution graph every few days and
    597.  
    598. # updating the auto-grader. We establish a bound for lowest & highest encountered numbers of nodes and edges with a
    599.  
    600. # margin of +/- 100 for nodes and +/- 150 for edges. e.g., The allowable range of nodes is set to:
    601.  
    602. #
    603.  
    604. # Min allowable nodes = min encountered nodes - 100
    605.  
    606. # Max allowable nodes = max allowable nodes + 100
    607.  
    608. #
    609.  
    610. # e.g., if the minimum encountered nodes = 507 and the max encountered nodes = 526, then the min/max range is 407-626
    611.  
    612. # The same method is used to calculate the edges with the exception of using the aforementioned edge margin.
    613.  
    614. # ----------------------------------------------------------------------------------------------------------------------
    615.  
    616. # BEGIN BUILD CO-ACTOR NETWORK
    617.  
    618. #
    619.  
    620. # INITIALIZE GRAPH
    621.  
    622. # Initialize a Graph object with a single node representing Laurence Fishburne
    623.  
    624. #
    625.  
    626. # BEGIN BUILD BASE GRAPH:
    627.  
    628. # Find all of Laurence Fishburne's movie credits that have a vote average >= 8.0
    629.  
    630. # FOR each movie credit:
    631.  
    632. # | get the movie cast members having an 'order' value between 0-2 (these are the co-actors)
    633.  
    634. # |
    635.  
    636. # | FOR each movie cast member:
    637.  
    638. # | | using graph.add_node(), add the movie cast member as a node (keep track of all new nodes added to the graph)
    639.  
    640. # | | using graph.add_edge(), add an edge between the Laurence Fishburne (actress) node
    641.  
    642. # | | and each new node (co-actor/co-actress)
    643.  
    644. # | END FOR
    645.  
    646. # END FOR
    647.  
    648. # END BUILD BASE GRAPH
    649.  
    650. #
    651.  
    652. #
    653.  
    654. # BEGIN LOOP - DO 2 TIMES:
    655.  
    656. # IF first iteration of loop:
    657.  
    658. # | nodes = The nodes added in the BUILD BASE GRAPH (this excludes the original node of Laurence Fishburne!)
    659.  
    660. # ELSE
    661.  
    662. # | nodes = The nodes added in the previous iteration:
    663.  
    664. # ENDIF
    665.  
    666. #
    667.  
    668. # FOR each node in nodes:
    669.  
    670. # | get the movie credits for the actor that have a vote average >= 8.0
    671.  
    672. # |
    673.  
    674. # | FOR each movie credit:
    675.  
    676. # | | try to get the 3 movie cast members having an 'order' value between 0-2
    677.  
    678. # | |
    679.  
    680. # | | FOR each movie cast member:
    681.  
    682. # | | | IF the node doesn't already exist:
    683.  
    684. # | | | | add the node to the graph (track all new nodes added to the graph)
    685.  
    686. # | | | ENDIF
    687.  
    688. # | | |
    689.  
    690. # | | | IF the edge does not exist:
    691.  
    692. # | | | | add an edge between the node (actor) and the new node (co-actor/co-actress)
    693.  
    694. # | | | ENDIF
    695.  
    696. # | | END FOR
    697.  
    698. # | END FOR
    699.  
    700. # END FOR
    701.  
    702. # END LOOP
    703.  
    704. #
    705.  
    706. # Your graph should not have any duplicate edges or nodes
    707.  
    708. # Write out your finished graph as a nodes file and an edges file using:
    709.  
    710. # graph.write_edges_file()
    711.  
    712. # graph.write_nodes_file()
    713.  
    714. #
    715.  
    716. # END BUILD CO-ACTOR NETWORK
    717.  
    718.  
    719. Actor_main_Graph = Graph()
    720.  
    721. tmdb_api_utils = TMDBAPIUtils(api_key='11cf6e0baa84777c109be80a6cffdab3')
    722.  
    723. Cast_details = tmdb_api_utils.get_movie_credits_for_person(2975, 8.0)
    724.  
    725. # print(len(Cast_details))
    726.  
    727. Actor_main_Graph.add_node(5064, 'Laurence Fishburne')
    728.  
    729. for i in Cast_details:
    730.  
    731. movie_cast = tmdb_api_utils.get_movie_cast(i['id'], limit=3)
    732.  
    733. #movie_cast = tmdb_api_utils.get_movie_cast(i['id'],limit=3,exclude_ids=[2975])
    734.  
    735. # print(movie_cast)
    736.  
    737. for cast in movie_cast:
    738.  
    739. Actor_main_Graph.add_node(cast['id'], cast['name'])
    740.  
    741. Actor_main_Graph.add_edge(cast['id'], 2975)
    742.  
    743.  
    744. count = 1
    745.  
    746. exclude_list = [2975]
    747.  
    748.  
    749. def test():
    750.  
    751. global count
    752.  
    753. for node in Actor_main_Graph.nodes[count:]:
    754.  
    755. count += 1
    756.  
    757. Cast_details = tmdb_api_utils.get_movie_credits_for_person(
    758. node[0], 8.0)
    759.  
    760.  
    761. #Actor_main_Graph.add_node(node[0], node[1])
    762.  
    763. for i in Cast_details:
    764.  
    765. movie_cast = tmdb_api_utils.get_movie_cast(
    766. i['id'], limit=3, exclude_ids=exclude_list)
    767.  
    768. print(movie_cast)
    769.  
    770. for cast in movie_cast:
    771.  
    772. Actor_main_Graph.add_node(cast['id'], cast['name'])
    773.  
    774. Actor_main_Graph.add_edge(cast['id'], node[0])
    775.  
    776. exclude_list.append(node[0])
    777.  
    778. test()
    779.  
    780.  
    781. # ----------------------------------------------------------------------------------------------------------------------
    782.  
    783. # ----------------------------------------------------------------------------------------------------------------------
    784.  
    785.  
    786. # Exception handling and best practices
    787.  
    788. # - You should use the param 'language=en-US' in all API calls to avoid encoding issues when writing data to file.
    789.  
    790. # - If the actor name has a comma char ',' it should be removed to prevent extra columns from being inserted into the .csv file
    791.  
    792. # - Some movie_credits may actually be collections and do not return cast data. Handle this situation by skipping these instances.
    793.  
    794. # - While The TMDb API does not have a rate-limiting scheme in place, consider that making hundreds / thousands of calls
    795.  
    796. # can occasionally result in timeout errors. If you continue to experience 'ConnectionRefusedError : [Errno 61] Connection refused',
    797.  
    798. # - wait a while and then try again. It may be necessary to insert periodic sleeps when you are building your graph.
    799.  
    800.  
    801. def return_name() -> str:
    802. """
    803.  
    804. Return a string containing your GT Username
    805.  
    806. e.g., gburdell3
    807.  
    808. Do not return your 9 digit GTId
    809.  
    810. """
    811.  
    812. username = 'deason7'
    813.  
    814. return username
    815.  
    816. # return NotImplemented
    817.  
    818.  
    819. def return_argo_lite_snapshot() -> str:
    820. """
    821.  
    822. Return the shared URL of your published graph in Argo-Lite
    823.  
    824. """
    825.  
    826. #url = ''
    827.  
    828. return url
    829.  
    830. # return NotImplemented
    831.  
    832.  
    833. # You should modify __main__ as you see fit to build/test your graph using the TMDBAPIUtils & Graph classes.
    834.  
    835. # Some boilerplate/sample code is provided for demonstration. We will not call __main__ during grading.
    836.  
    837.  
    838. if __name__ == "__main__":
    839.  
    840. graph = Graph()
    841.  
    842. graph.add_node(id='2975', name='Laurence Fishburne')
    843.  
    844. tmdb_api_utils = TMDBAPIUtils(api_key='11cf6e0baa84777c109be80a6cffdab3')
    845.  
    846. # call functions or place code here to build graph (graph building code not graded)
    847.  
    848. # Suggestion: code should contain steps outlined above in BUILD CO-ACTOR NETWORK
    849.  
    850. graph.write_edges_file()
    851.  
    852. graph.write_nodes_file()
    853.  
    854. # If you have already built & written out your graph, you could read in your nodes & edges files
    855.  
    856. # to perform testing on your graph.
    857.  
    858. # graph = Graph(with_edges_file="edges.csv", with_nodes_file="nodes.csv")
    859.  
    860. #x = TMDBAPIUtils('11cf6e0baa84777c109be80a6cffdab3')
    861.  
    862. #print(x.get_movie_credits_for_person('500', 5.0))# your code goes here